Compare commits
No commits in common. 'php-unit-testing' and 'master' have entirely different histories.
php-unit-t
...
master
@ -1,39 +0,0 @@
|
||||
---
|
||||
engines:
|
||||
csslint:
|
||||
enabled: true
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- javascript
|
||||
- php
|
||||
eslint:
|
||||
enabled: true
|
||||
fixme:
|
||||
enabled: true
|
||||
phpmd:
|
||||
enabled: true
|
||||
checks:
|
||||
Controversial/CamelCaseClassName:
|
||||
enabled: false
|
||||
Controversial/CamelCaseMethodName:
|
||||
enabled: false
|
||||
Controversial/CamelCasePropertyName:
|
||||
enabled: false
|
||||
Controversial/CamelCaseVariableName:
|
||||
enabled: false
|
||||
Controversial/Superglobals:
|
||||
enabled: false
|
||||
CleanCode/ElseExpression:
|
||||
enabled: false
|
||||
CleanCode/StaticAccess:
|
||||
enabled: false
|
||||
ratings:
|
||||
paths:
|
||||
- "css/privatebin.css"
|
||||
- "css/bootstrap/privatebin.css"
|
||||
- "js/privatebin.js"
|
||||
- "lib/**.php"
|
||||
- "index.php"
|
||||
exclude_paths: []
|
@ -1,2 +0,0 @@
|
||||
--exclude-exts=.min.css
|
||||
--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes
|
@ -1,18 +1,8 @@
|
||||
# Documentation, might leak version number
|
||||
CHANGELOG.md
|
||||
LICENSE.md
|
||||
CREDITS.md
|
||||
INSTALL.md
|
||||
# Docs
|
||||
README.md
|
||||
doc/
|
||||
|
||||
# Dotfiles, pointless
|
||||
.codeclimate.yml
|
||||
.csslintrc
|
||||
.editorconfig
|
||||
.eslint*
|
||||
.git*
|
||||
.php_cs
|
||||
.styleci.yml
|
||||
.travis.yml
|
||||
.github
|
||||
# Git
|
||||
.git/
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
@ -0,0 +1,47 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: default
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: publish
|
||||
pull: default
|
||||
image: plugins/docker:18.09
|
||||
settings:
|
||||
registry: https://registry.nixaid.com
|
||||
repo: "registry.nixaid.com/${DRONE_REPO_NAMESPACE}/${DRONE_REPO_NAME}"
|
||||
tags:
|
||||
- latest
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
# storage_path: /drone/docker
|
||||
# storage_driver: aufs
|
||||
# ipv6: false
|
||||
# debug: true
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
- name: notify
|
||||
pull: default
|
||||
image: drillster/drone-email:latest
|
||||
settings:
|
||||
from: "Drone CI <noreply@nixaid.com>"
|
||||
host: mx.nixaid.com
|
||||
port: 587
|
||||
subject: "NIXAID Drone Pipeline {{#success build.status}}SUCCESS{{else}}FAILURE{{/success}} Notification"
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
status:
|
||||
- success
|
||||
- failure
|
@ -1,43 +0,0 @@
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
# Unix style files
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.css]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.json]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.jsonld]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.php]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{htm,html}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.{md,markdown}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
@ -1 +0,0 @@
|
||||
**/*{.,-}min.js
|
@ -1,216 +0,0 @@
|
||||
ecmaFeatures:
|
||||
modules: true
|
||||
jsx: true
|
||||
|
||||
env:
|
||||
amd: true
|
||||
browser: true
|
||||
es6: true
|
||||
jquery: true
|
||||
node: true
|
||||
|
||||
globals:
|
||||
sjcl: false
|
||||
|
||||
# http://eslint.org/docs/rules/
|
||||
rules:
|
||||
# Possible Errors
|
||||
comma-dangle: [2, never]
|
||||
no-cond-assign: 2
|
||||
no-console: 0
|
||||
no-constant-condition: 2
|
||||
no-control-regex: 2
|
||||
no-debugger: 2
|
||||
no-dupe-args: 2
|
||||
no-dupe-keys: 2
|
||||
no-duplicate-case: 2
|
||||
no-empty: 2
|
||||
no-empty-character-class: 2
|
||||
no-ex-assign: 2
|
||||
no-extra-boolean-cast: 2
|
||||
no-extra-parens: 0
|
||||
no-extra-semi: 2
|
||||
no-func-assign: 2
|
||||
no-inner-declarations: [2, functions]
|
||||
no-invalid-regexp: 2
|
||||
no-irregular-whitespace: 2
|
||||
no-negated-in-lhs: 2
|
||||
no-obj-calls: 2
|
||||
no-regex-spaces: 2
|
||||
no-sparse-arrays: 2
|
||||
no-unexpected-multiline: 2
|
||||
no-unreachable: 2
|
||||
use-isnan: 2
|
||||
valid-jsdoc: 0
|
||||
valid-typeof: 2
|
||||
|
||||
# Best Practices
|
||||
accessor-pairs: 2
|
||||
block-scoped-var: 0
|
||||
complexity: [2, 6]
|
||||
consistent-return: 0
|
||||
curly: 0
|
||||
default-case: 0
|
||||
dot-location: 0
|
||||
dot-notation: 0
|
||||
eqeqeq: 2
|
||||
guard-for-in: 2
|
||||
no-alert: 0
|
||||
no-caller: 2
|
||||
no-case-declarations: 2
|
||||
no-div-regex: 2
|
||||
no-else-return: 0
|
||||
no-empty-label: 2
|
||||
no-empty-pattern: 2
|
||||
no-eq-null: 2
|
||||
no-eval: 2
|
||||
no-extend-native: 2
|
||||
no-extra-bind: 2
|
||||
no-fallthrough: 2
|
||||
no-floating-decimal: 0
|
||||
no-implicit-coercion: 0
|
||||
no-implied-eval: 2
|
||||
no-invalid-this: 0
|
||||
no-iterator: 2
|
||||
no-labels: 0
|
||||
no-lone-blocks: 2
|
||||
no-loop-func: 2
|
||||
no-magic-number: 0
|
||||
no-multi-spaces: 0
|
||||
no-multi-str: 0
|
||||
no-native-reassign: 2
|
||||
no-new-func: 2
|
||||
no-new-wrappers: 2
|
||||
no-new: 2
|
||||
no-octal-escape: 2
|
||||
no-octal: 2
|
||||
no-proto: 2
|
||||
no-redeclare: 2
|
||||
no-return-assign: 2
|
||||
no-script-url: 2
|
||||
no-self-compare: 2
|
||||
no-sequences: 0
|
||||
no-throw-literal: 0
|
||||
no-unused-expressions: 2
|
||||
no-useless-call: 2
|
||||
no-useless-concat: 2
|
||||
no-void: 2
|
||||
no-warning-comments: 0
|
||||
no-with: 2
|
||||
radix: 2
|
||||
vars-on-top: 0
|
||||
wrap-iife: 2
|
||||
yoda: 0
|
||||
|
||||
# Strict
|
||||
strict: 0
|
||||
|
||||
# Variables
|
||||
init-declarations: 0
|
||||
no-catch-shadow: 2
|
||||
no-delete-var: 2
|
||||
no-label-var: 2
|
||||
no-shadow-restricted-names: 2
|
||||
no-shadow: 0
|
||||
no-undef-init: 2
|
||||
no-undef: 0
|
||||
no-undefined: 0
|
||||
no-unused-vars: 0
|
||||
no-use-before-define: 0
|
||||
|
||||
# Node.js and CommonJS
|
||||
callback-return: 2
|
||||
global-require: 2
|
||||
handle-callback-err: 2
|
||||
no-mixed-requires: 0
|
||||
no-new-require: 0
|
||||
no-path-concat: 2
|
||||
no-process-exit: 2
|
||||
no-restricted-modules: 0
|
||||
no-sync: 0
|
||||
|
||||
# Stylistic Issues
|
||||
array-bracket-spacing: 0
|
||||
block-spacing: 0
|
||||
brace-style: 0
|
||||
camelcase: 0
|
||||
comma-spacing: 0
|
||||
comma-style: 0
|
||||
computed-property-spacing: 0
|
||||
consistent-this: 0
|
||||
eol-last: 0
|
||||
func-names: 0
|
||||
func-style: 0
|
||||
id-length: 0
|
||||
id-match: 0
|
||||
indent: 0
|
||||
jsx-quotes: 0
|
||||
key-spacing: 0
|
||||
linebreak-style: 0
|
||||
lines-around-comment: 0
|
||||
max-depth: 0
|
||||
max-len: 0
|
||||
max-nested-callbacks: 0
|
||||
max-params: 0
|
||||
max-statements: [2, 30]
|
||||
new-cap: 0
|
||||
new-parens: 0
|
||||
newline-after-var: 0
|
||||
no-array-constructor: 0
|
||||
no-bitwise: 0
|
||||
no-continue: 0
|
||||
no-inline-comments: 0
|
||||
no-lonely-if: 0
|
||||
no-mixed-spaces-and-tabs: 0
|
||||
no-multiple-empty-lines: 0
|
||||
no-negated-condition: 0
|
||||
no-nested-ternary: 0
|
||||
no-new-object: 0
|
||||
no-plusplus: 0
|
||||
no-restricted-syntax: 0
|
||||
no-spaced-func: 0
|
||||
no-ternary: 0
|
||||
no-trailing-spaces: 0
|
||||
no-underscore-dangle: 0
|
||||
no-unneeded-ternary: 0
|
||||
object-curly-spacing: 0
|
||||
one-var: 0
|
||||
operator-assignment: 0
|
||||
operator-linebreak: 0
|
||||
padded-blocks: 0
|
||||
quote-props: 0
|
||||
quotes: 0
|
||||
require-jsdoc: 0
|
||||
semi-spacing: 0
|
||||
semi: 0
|
||||
sort-vars: 0
|
||||
space-after-keywords: 0
|
||||
space-before-blocks: 0
|
||||
space-before-function-paren: 0
|
||||
space-before-keywords: 0
|
||||
space-in-parens: 0
|
||||
space-infix-ops: 0
|
||||
space-return-throw-case: 0
|
||||
space-unary-ops: 0
|
||||
spaced-comment: 0
|
||||
wrap-regex: 0
|
||||
|
||||
# ECMAScript 6
|
||||
arrow-body-style: 0
|
||||
arrow-parens: 0
|
||||
arrow-spacing: 0
|
||||
constructor-super: 0
|
||||
generator-star-spacing: 0
|
||||
no-arrow-condition: 0
|
||||
no-class-assign: 0
|
||||
no-const-assign: 0
|
||||
no-dupe-class-members: 0
|
||||
no-this-before-super: 0
|
||||
no-var: 0
|
||||
object-shorthand: 0
|
||||
prefer-arrow-callback: 0
|
||||
prefer-const: 0
|
||||
prefer-reflect: 0
|
||||
prefer-spread: 0
|
||||
prefer-template: 0
|
||||
require-yield: 0
|
@ -1,19 +0,0 @@
|
||||
doc/ export-ignore
|
||||
tst/ export-ignore
|
||||
js/.istanbul.yml export-ignore
|
||||
js/test.js export-ignore
|
||||
js/mocha-3.2.0.js export-ignore
|
||||
css/mocha-3.2.0.css export-ignore
|
||||
.codeclimate.yml export-ignore
|
||||
.csslintrc export-ignore
|
||||
.dockerignore export-ignore
|
||||
.editorconfig export-ignore
|
||||
.eslintignore export-ignore
|
||||
.eslintrc export-ignore
|
||||
.gitattributes export-ignore
|
||||
.github export-ignore
|
||||
.gitignore export-ignore
|
||||
.php_cs export-ignore
|
||||
.styleci.yml export-ignore
|
||||
.travis.yml export-ignore
|
||||
Dockerfile export-ignore
|
@ -1,8 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
At first, awesome you take the time to make PrivateBin better! :tada: :+1:
|
||||
|
||||
Have a look at our [contributing guide](https://github.com/PrivateBin/PrivateBin/wiki/Development) if you want to hack on the code.
|
||||
If you want to translate PrivateBin into your language have a look at the [translation guide](https://github.com/PrivateBin/PrivateBin/wiki/Translation).
|
||||
|
||||
Except this also opening [issues](https://github.com/PrivateBin/PrivateBin/issues) helps much. Just describe your problem detailed enough and fill out our template.
|
@ -1,39 +0,0 @@
|
||||
<!-- Please have a look at our FAQ before submitting an issue: https://github.com/PrivateBin/PrivateBin/wiki/FAQ -->
|
||||
<!-- This is a template for a bug report. If you would like to suggest a feature, feel free to delete the part below. -->
|
||||
|
||||
## Steps to reproduce
|
||||
<!-- Tell us how to reproduce the problem. -->
|
||||
1.
|
||||
2.
|
||||
|
||||
### What happens
|
||||
|
||||
|
||||
### What should happen
|
||||
|
||||
|
||||
## Additional information
|
||||
<!--
|
||||
Here you can add screenshots. If the issue is e.g. a client-side issue (= an issue, which happens in your browser) press F12 and copy and paste the console output or add a screenshot.
|
||||
If you have access to the server log files, also copy them here.
|
||||
-->
|
||||
|
||||
## Basic information
|
||||
|
||||
<!-- If you use a public server enter the address of it here. -->
|
||||
**Server address**:
|
||||
|
||||
<!-- The Operation System of your server -->
|
||||
**Server OS:**
|
||||
|
||||
<!-- The webserver running on your server, preferrably including the version -->
|
||||
**Webserver:**
|
||||
|
||||
<!-- The version of your browser (when it is a client-side issue) -->
|
||||
**Browser:**
|
||||
|
||||
<!-- The version of PrivateBin, if you use an unstable version paste the commit hash or the GitHub link to the commit here (you can get it by running `git rev-parse HEAD`) -->
|
||||
**PrivateBin version:**
|
||||
|
||||
* I can reproduce this issue on <https://privatebin.net>: Yes / No
|
||||
|
@ -1,17 +0,0 @@
|
||||
<!-- This is a template for your Pull Request. This are just some suggestions for you. You do not have to use all of them. -->
|
||||
|
||||
<!-- If your PR fixes an issue, mention it here. You can also just copy the URL - GitHub will convert it for you.
|
||||
If this PR fixes several issues, please prepend each issue url/number with the word "fix"/"fixes" or "close"/"closes" as this automatically closes the issues you mentioned when the PR is merged.
|
||||
-->
|
||||
This PR fixes
|
||||
|
||||
## Changes
|
||||
<!-- List all the changes you have done -->
|
||||
*
|
||||
*
|
||||
|
||||
## ToDo
|
||||
<!-- Add things, you still want to do. It is recommend to put "[DNM]", "[DONOTMERGE]", "[WIP]" or "[WORKINPROGRESS]" **into the title** of your PR if you still want to work on this PR, but just do not want to have it merged yet. -->
|
||||
* [ ]
|
||||
* [ ]
|
||||
* [ ]
|
@ -1,36 +0,0 @@
|
||||
# Ignore server files for safety
|
||||
.htaccess
|
||||
.htpasswd
|
||||
|
||||
# Ignore data/
|
||||
data/
|
||||
|
||||
# Ignore PhpDoc
|
||||
doc/*
|
||||
!doc/*.md
|
||||
|
||||
# Ignore developers composer status so it isn't accidentally checked in,
|
||||
# see https://github.com/PrivateBin/PrivateBin/issues/84
|
||||
composer.lock
|
||||
|
||||
# Ignore vendor dir of Composer except PHP files
|
||||
vendor/*.*
|
||||
vendor/*/*.*
|
||||
vendor/*/*/*.*
|
||||
vendor/*/*/*/*.*
|
||||
vendor/*/*/*/*/*.*
|
||||
vendor/*/*/*/*/*/*.*
|
||||
vendor/**/LICENSE
|
||||
vendor/**/test
|
||||
vendor/**/tst
|
||||
vendor/**/tests
|
||||
vendor/**/build_phar.php
|
||||
!vendor/**/*.php
|
||||
|
||||
# Ignore local node modules, unit testing logs, api docs and eclipse project files
|
||||
js/node_modules/
|
||||
tst/log/
|
||||
.settings
|
||||
.buildpath
|
||||
.project
|
||||
.externalToolBuilders
|
@ -1,3 +0,0 @@
|
||||
RewriteEngine on
|
||||
RewriteCond %{HTTP_USER_AGENT} ^.*(bot|spider|crawl|https?://|WhatsApp|SkypeUriPreview|facebookexternalhit) [NC]
|
||||
RewriteRule .* - [R=403,L]
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Configuration file for PHP Coding Standards Fixer (php-cs-fixer).
|
||||
*
|
||||
* On GitHub: https://github.com/FriendsOfPhp/php-cs-fixer
|
||||
* More information: http://cs.sensiolabs.org/
|
||||
*/
|
||||
|
||||
$finder = Symfony\CS\Finder\DefaultFinder::create()
|
||||
->in('lib')
|
||||
;
|
||||
|
||||
return Symfony\CS\Config\Config::create()
|
||||
->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
|
||||
->fixers(['concat_with_spaces', 'long_array_syntax', 'standardize_not_equal',
|
||||
'operators_spaces', 'duplicate_semicolon',
|
||||
'remove_leading_slash_use', 'align_equals',
|
||||
'single_array_no_trailing_comma', 'phpdoc_indent', 'phpdoc_order',
|
||||
'phpdoc_scalar', 'phpdoc_to_comment', 'phpdoc_trim',
|
||||
'phpdoc_types', 'print_to_echo', 'self_accessor', 'single_quote',
|
||||
'spaces_cast', 'ternary_spaces'])
|
||||
->finder($finder)
|
||||
;
|
@ -1,26 +0,0 @@
|
||||
preset: recommended
|
||||
|
||||
risky: false
|
||||
|
||||
enabled:
|
||||
- no_empty_comment
|
||||
- align_equals
|
||||
- long_array_syntax
|
||||
- concat_with_spaces
|
||||
|
||||
disabled:
|
||||
- blank_line_after_opening_tag
|
||||
- blank_line_before_return
|
||||
- concat_without_spaces
|
||||
- declare_equal_normalize
|
||||
- heredoc_to_nowdoc
|
||||
- method_argument_space
|
||||
- new_with_braces
|
||||
- phpdoc_align
|
||||
- phpdoc_no_access
|
||||
- phpdoc_separation
|
||||
- phpdoc_single_line_var_spacing
|
||||
- phpdoc_summary
|
||||
- short_array_syntax
|
||||
- single_line_after_imports
|
||||
- unalign_equals
|
@ -1,17 +0,0 @@
|
||||
language: php
|
||||
sudo: false
|
||||
php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
|
||||
before_script:
|
||||
- composer install -n
|
||||
|
||||
script:
|
||||
- cd tst && ../vendor/phpunit/phpunit/phpunit
|
||||
|
||||
after_script:
|
||||
- cd ..
|
||||
- vendor/bin/codacycoverage clover tst/log/coverage-clover.xml
|
||||
- vendor/bin/test-reporter --coverage-report tst/log/coverage-clover.xml
|
@ -1,153 +0,0 @@
|
||||
# PrivateBin version history
|
||||
|
||||
* **next (not yet released)**
|
||||
* ADDED: Translations for Spanish, Occitan and Norwegian
|
||||
* ADDED: Option in configuration to change the default "PrivateBin" title of the site
|
||||
* CHANGED: Cleanup of bootstrap template variants and moved icons to `img` directory
|
||||
* **1.1 (2016-12-26)**
|
||||
* ADDED: Translations for Italian and Russian
|
||||
* ADDED: Loading message displayed until decryption succeeded for slower (in terms of CPU or network) systems
|
||||
* ADDED: Dockerfile for docker container creation
|
||||
* CHANGED: Using modal dialog to request password input instead of native JS input window (#69)
|
||||
* CHANGED: Suppressed referrer HTTP header sending when following links in a paste or comment (#96) and added additional HTTP headers for XSS mitigation (#91)
|
||||
* CHANGED: Updated random_compat and jQuery libraries
|
||||
* FIXED: XSS using JavaScript stored as markdown formatted paste, after clicking on Raw paste button (#137)
|
||||
* FIXED: Automatic purging deleting non-expiring pastes, when using database store (#149)
|
||||
* **1.0 (2016-08-25)**
|
||||
* ADDED: Translations for Slowene and Chinese
|
||||
* ADDED: re-introduced (optional) URL shortener support, which was removed back in version 0.16 for privacy concerns
|
||||
* ADDED: Preview tab, helpful for writing markdown code or check the source code rendering
|
||||
* ADDED: Automatic purging of expired pastes, done on paste creation
|
||||
* ADDED: Option to disable icons in discussions (will only affect newly created pastes)
|
||||
* ADDED: Composer support
|
||||
* CHANGED: Renamed the ZeroBin fork to PrivateBin
|
||||
* CHANGED: Removed unmaintained RainTPL template engine, replacing the templates with straight forward PHP files
|
||||
* CHANGED: New logo and favicons
|
||||
* CHANGED: Upgrading SJCL library to 1.0.4
|
||||
* CHANGED: Switched to GCM instead of CCM mode for AES encryption for newly created pastes
|
||||
* CHANGED: Use backported random bytes function from PHP7 for older PHP versions instead of mcrypt
|
||||
* CHANGED: Switched to a SHA256 HMAC of the IP in traffic limiter instead of storing it in plain text on the server
|
||||
* CHANGED: Introduced content security policy header to reduce cross site scripting (XSS) risks
|
||||
* CHANGED: Added SHA512 subresource integrity hashes for all javascript includes to reduce the risk of manipulated scripts and easier detection of such
|
||||
* CHANGED: Refactored PHP code to conform to PSR-4 and PSR-2 standards
|
||||
* CHANGED: Switched to Identicons as the default for comments with nicknames
|
||||
* CHANGED: Vizhash is now optional and based on (128 byte) SHA512 HMAC instead of (144 byte) combination of MD5, SHA1 and a reversal of that string
|
||||
* FIXED: Content-type negociation for HTML in certain uncommon browser configurations
|
||||
* FIXED: JavaScript error displayed before page is loaded or during attachment load
|
||||
* FIXED: Don't strip space characters at beginning or end of optional password
|
||||
* FIXED: Various UI glitches in mobile version or on smaller desktops with language menu, button spacing and long URLs
|
||||
* FIXED: Back button now works as expected after switching to raw text view of a paste
|
||||
* FIXED: Reactivated second error message above send comment button to ensure its visibility when the main error message is outside the viewport
|
||||
* FIXED: Raw text now displays original markdown instead of rendered HTML
|
||||
* FIXED: Removed unused code detected with the help of various code review tools
|
||||
* FIXED: Table format for PostgreSQL, making it possible to use PostgreSQL as backend in addition to MySQL, SQLite and flat files
|
||||
* **0.22 (2015-11-09)**:
|
||||
* ADDED: Tab character input support
|
||||
* ADDED: Dark bootstrap theme
|
||||
* ADDED: Option to hide clone button on expiring pastes
|
||||
* ADDED: Option to set a different default language then English and/or enforce it as the only language
|
||||
* ADDED: Database now contains version to allow automatic update of structure, only if necessary; removing database structure check on each request
|
||||
* ADDED: Favicons
|
||||
* FIXING: Regressions in database layer, prohibiting pastes from being stored
|
||||
* FIXING: Fixing "missing" comments when they were posted during the same second to the same paste
|
||||
* FIXING: JS failing when password input disabled
|
||||
* CHANGED: Switching positions of "New" and "Send" button, highlighting the latter to improve workflow
|
||||
* CHANGED: Renamed config file to make updates easier
|
||||
* CHANGED: Switching to JSON-based REST-API
|
||||
* CHANGED: Database structure to store attachments, allowing larger attachments to be stored (depending on maximum BLOB size of database backend)
|
||||
* CHANGED: Refactored data model, traffic limiting & request handling
|
||||
* **0.21.1 (2015-09-21)**:
|
||||
* FIXING: lost meta data when using DB model instead of flat files
|
||||
* FIXING: mobile navbar getting triggered on load
|
||||
* CHANGED: database table "paste" gets automatically extended with a "meta" column
|
||||
* CHANGED: navbar of "bootstrap" template now spans full width of view port on large screens
|
||||
* **0.21 (2015-09-19)**:
|
||||
* ADDED: Translations for German, French and Polish, language selection menu (optional)
|
||||
* ADDED: File upload and image display support (optional)
|
||||
* ADDED: Markdown format support
|
||||
* ADDED: "bootstrap-compact" template that hides some of the options in a drop down menu to ensure the nav bar fitting on one line on smaller screen sizes
|
||||
* FIXING: Various usability issues with different screen sizes / device types in the "bootstrap" template
|
||||
* CHANGED: Instead of having different options to enable and preselect certain formats there is now a generic `[formatter_options]` section where formats can be added to the displayed format drop down menu. A `defaultformatter` can be set, it defaults to "plaintext". The `syntaxhighlighting` configuration got deprecated.
|
||||
* `zerobin.js` got a major refactoring:
|
||||
* moved from global namespace into anonymous function
|
||||
* events are no longer set via "onclick" attributes in the templates, but bound by from JS side
|
||||
* for simpler maintenance the functions were grouped into objects: zerobin (display logic, event handling), filter (compression,
|
||||
encryption), i18n (translation, counterpart of i18n.php) and helper (stateless utilities)
|
||||
* Wiki pages were added to address common topics:
|
||||
* [Upgrading from ZeroBin 0.19 Alpha](https://github.com/PrivateBin/PrivateBin/wiki/Upgrading-from-ZeroBin-0.19-Alpha)
|
||||
* [Directory of public PrivateBin servers](https://github.com/PrivateBin/PrivateBin/wiki/PrivateBin-Directory)
|
||||
* [Translation](https://github.com/PrivateBin/PrivateBin/wiki/Translation)
|
||||
* [Templates](https://github.com/PrivateBin/PrivateBin/wiki/Templates)
|
||||
* **0.20 (2015-09-03)**:
|
||||
* ADDED: Password protected pastes (optional)
|
||||
* ADDED: configuration options for highlighting, password, discussions, expiration times, rate limiting
|
||||
* ADDED: JSON-only retrieval of paste incl. discussion, used to be able to refresh paste when posting a comment
|
||||
* ADDED: bootstrap CSS based template
|
||||
* CHANGED: "Burn after reading" pastes are now deleted only after the paste was successfully decrypted via callback. This prevents accidental deletion by chatbots following URLs and the like. Usage of a password is suggested to ensure only the desired recipient is able to encrypt it.
|
||||
* CHANGED: the "opendiscussion" option now only controls if the discussion checkbox is preselected. Use "discussion = false" to disable the discussion feature completely (which also removes the checkbox from the template).
|
||||
* FIXING: Behaviour of several conflicting configuration options. As a general measure unit tests for 9 of the options and all their possible configurations were added via a unit test generator.
|
||||
* updated JS libraries: jquery to 1.11.3, sjcl to 1.0.2, base64.js to 2.1.9, deflate to 0.5, inflate to 0.3 and prettify to latest
|
||||
* generally improved documentation, both inline phpdoc / JSdoc source code documentation, as well as Wiki pages on installation, configuration, development and JSON-API
|
||||
* **Alpha 0.19 (2013-07-05)**:
|
||||
* Corrected XSS security flaw which affected IE<10. Other browsers were not affected.
|
||||
* Corrected spacing display in IE<10.
|
||||
* **Alpha 0.18 (2013-02-24)**:
|
||||
* ADDED: The resulting URL is automatically selected after pressing "Send". You just have to press CTRL+C.
|
||||
* ADDED: Automatic syntax highlighting for 53 languages using highlight.js
|
||||
* ADDED: "5 minutes" and "1 week" expirations.
|
||||
* ADDED: "Raw text" button.
|
||||
* jQuery upgraded to 1.9.1
|
||||
* sjcl upgraded to GitHub master 2013-02-23
|
||||
* base64.js upgraded to 1.7
|
||||
* FIXED: Dates in discussion are now proper local dates.
|
||||
* ADDED: Robot meta tags in HTML to prevent search engines indexing.
|
||||
* ADDED: Better json checking (including entropy).
|
||||
* ADDED: Added version to js/css assets URLs in order to prevent some abusive caches to serve an obsolete version of these files when ZeroBin is upgraded.
|
||||
* "Burn after reading" option has been moved out of Expiration combo to a separate checkbox. Reason is: You can prevent a read-once paste to be available ad vitam eternam on the net.
|
||||
* **Alpha 0.17 (2013-02-23)**:
|
||||
* ADDED: Deletion URL.
|
||||
* small refactoring.
|
||||
* improved regex checks.
|
||||
* larger server alt on installation.
|
||||
* **Alpha 0.16**:
|
||||
* FIXED minor php warnings.
|
||||
* FIXED: zerobin.js reformated and properly commented.
|
||||
* FIXED: Directory structure re-organized.
|
||||
* CHANGED: URL shortening button was removed. (It was bad for privacy.)
|
||||
* **Alpha 0.15 (2012-04-20):**
|
||||
* FIXED: 2 minor corrections to avoid notices in php log.
|
||||
* FIXED: Sources converted to UTF-8.
|
||||
* **Alpha 0.14 (2012-04-20):**
|
||||
* ADDED: GD presence is checked.
|
||||
* CHANGED: Traffic limiter data files moved to data/ (→easier rights management)
|
||||
* ADDED: "Burn after reading" implemented. Opening the URL will display the paste and immediately destroy it on server.
|
||||
* **Alpha 0.13 (2012-04-18):**
|
||||
* FIXED: ''imageantialias()'' call removed because it's not really usefull and can be a problem on most hosts (if GD is not compiled in php).
|
||||
* FIXED: $error not properly initialized in index.php
|
||||
* **Alpha 0.12 (2012-04-18):**
|
||||
* **DISCUSSIONS !** Now you can enable discussions on your pastes. Of course, posted comments and nickname are also encrypted and the server cannot see them.
|
||||
* This feature implies a change in storage format. You will have to delete all previous pastes in your ZeroBin.
|
||||
* Added [[php:vizhash_gd|Vizhash]] as avatars, so you can match posters IP addresses without revealing them. (Same image = same IP). Of course the IP address cannot be deduced from the Vizhash.
|
||||
* Remaining time before expiration is now displayed.
|
||||
* Explicit tags were added to CSS and jQuery selectors (eg. div#aaa instead of #aaa) to speed up browser.
|
||||
* Better cleaning of the URL (to make sure the key is not broken by some stupid redirection service)
|
||||
* **Alpha 0.11 (2012-04-12):**
|
||||
* Automatically ignore parameters (such as &utm_source=...) added //after// the anchor by some stupid Web 2.0 services.
|
||||
* First public release.
|
||||
* **Alpha 0.10 (2012-04-12):**
|
||||
* IE9 does not seem to correctly support ''pre-wrap'' either. Special handling mode activated for all version of IE<10. (Note: **ALL other browsers** correctly support this feature.)
|
||||
* **Alpha 0.9 (2012-04-11):**
|
||||
* Oh bummer... IE 8 is as shitty as IE6/7: Its does not seem to support ''white-space:pre-wrap'' correctly. I had to activate the special handling mode. I still have to test IE 9.
|
||||
* **Alpha 0.8 (2012-04-11):**
|
||||
* Source code not published yet.
|
||||
* Interface completely redesigned. Icons added.
|
||||
* Now properly supports IE6/7 (ugly display, but it works. "Clone" button is disabled though.)
|
||||
* Added one level of depth for storage directories (This is better for higher load servers).
|
||||
* php version is now checked (min: 5.2.6)
|
||||
* Better checks on posted json data on server.
|
||||
* Added "1 year" expiration.
|
||||
* URLs are now converted to clickable links. This include http, https, ftp and magnet links.
|
||||
* Clickable links include ''rel="nofollow"'' to discourage SEO.
|
||||
* On my public service (http://sebsauvage.net/paste/)
|
||||
* All data will be deleted (you were warned - this is a test service)
|
||||
* Default paste expiration is now 1 month to prevent clogging-up my host.
|
@ -1,37 +0,0 @@
|
||||
# Credits
|
||||
|
||||
## Active contributors
|
||||
|
||||
Simon Rupf - current developer and maintainer
|
||||
rugk - security review, doc improvment & various other stuff
|
||||
|
||||
## Past contributions
|
||||
|
||||
Sébastien Sauvage - original idea and main developer
|
||||
|
||||
* Alexey Gladkov - syntax highlighting
|
||||
* Greg Knaddison - robots.txt
|
||||
* MrKooky - HTML5 markup, CSS cleanup
|
||||
* Simon Rupf - MVC refactoring, configuration, i18n and unit tests
|
||||
* Hexalyse - Password protection
|
||||
* Viktor Stanchev - File upload support
|
||||
* azlux - Tab character input support
|
||||
* Adam Fisher - old Favicons
|
||||
* rugk - new logo/icons
|
||||
* Sobak - PSR-4 and PSR-2 refactoring
|
||||
* Nathaniel Olsen - jQuery upgrade
|
||||
* Alexander Demenshin - modal password dialog
|
||||
* PunKeel - Dockerfile
|
||||
|
||||
## Translations
|
||||
* Hexalyse - French
|
||||
* Kuba Niewiarowski - Polish
|
||||
* Gabbalo - German
|
||||
* Draky50110 - French
|
||||
* Filip Muki Dobranić - Slovene
|
||||
* Jiawei Zhou - Chinese
|
||||
* Stefano Marty - Italian
|
||||
* R4SAS - Russian
|
||||
* Alfredo Fabián Altamirano Tena - Spanish
|
||||
* Quent-in - Occitan
|
||||
* idarlund - Norwegian
|
@ -1,17 +1,49 @@
|
||||
FROM php:apache
|
||||
FROM alpine:3.14
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libfreetype6-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng12-dev \
|
||||
wget \
|
||||
zip \
|
||||
unzip; \
|
||||
# We install and enable php-gd
|
||||
docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/; \
|
||||
docker-php-ext-install -j$(nproc) gd; \
|
||||
LABEL maintainer="andrey.arapov@nixaid.com"
|
||||
|
||||
# We enable Apache's mod_rewrite
|
||||
a2enmod rewrite
|
||||
ENV RELEASE 1.3.5
|
||||
ENV PBURL https://github.com/PrivateBin/PrivateBin/
|
||||
|
||||
COPY . .
|
||||
RUN \
|
||||
# Install dependencies
|
||||
apk add --no-cache gnupg php7-fpm php7-json php7-gd \
|
||||
php7-opcache php7-pdo_mysql php7-pdo_pgsql tzdata \
|
||||
&& apk upgrade --no-cache \
|
||||
# Install PrivateBin
|
||||
&& export GNUPGHOME="$(mktemp -d)" \
|
||||
&& gpg2 --list-public-keys || /bin/true \
|
||||
&& wget -qO - https://privatebin.info/key/release.asc | gpg2 --import - \
|
||||
&& cd /tmp \
|
||||
&& wget -qO ${RELEASE}.tar.gz.asc ${PBURL}releases/download/${RELEASE}/PrivateBin-${RELEASE}.tar.gz.asc \
|
||||
&& wget -q ${PBURL}archive/${RELEASE}.tar.gz \
|
||||
&& gpg2 --verify ${RELEASE}.tar.gz.asc \
|
||||
&& mkdir /var/www \
|
||||
&& cd /var/www \
|
||||
&& tar -xzf /tmp/${RELEASE}.tar.gz --strip 1 \
|
||||
&& rm *.md cfg/conf.sample.php \
|
||||
&& mv cfg lib tpl vendor /srv \
|
||||
&& mkdir /srv/data \
|
||||
&& sed -i "s#define('PATH', '');#define('PATH', '/srv/');#" index.php \
|
||||
&& rm -rf "${GNUPGHOME}" /tmp/* \
|
||||
&& apk del gnupg
|
||||
|
||||
# nginx group id must match to the nginx group id of the container running nginx (e.g. "nginx:mainline-alpine")
|
||||
ENV NGINXGID 101
|
||||
RUN addgroup -S -g $NGINXGID nginx
|
||||
|
||||
# Create the application user under which PHP-FPM will run
|
||||
ENV USER user
|
||||
ENV UID 1000
|
||||
ENV HOME /home/$USER
|
||||
ENV DATA /var/www
|
||||
RUN adduser -D -u $UID -h $HOME -s /bin/true $USER && \
|
||||
mkdir -p $DATA && \
|
||||
chown -Rh $USER:$NGINXGID $DATA /srv
|
||||
|
||||
# Copy the php-fpm & nginx configs
|
||||
COPY etc/ /etc/
|
||||
|
||||
WORKDIR $DATA
|
||||
USER $USER
|
||||
CMD php-fpm7 -F
|
||||
|
@ -1,149 +0,0 @@
|
||||
# Installation
|
||||
|
||||
**TL;DR:** Download the
|
||||
[latest release archive](https://github.com/PrivateBin/PrivateBin/releases/latest)
|
||||
and extract it in your web hosts folder where you want to install your PrivateBin
|
||||
instance. We try to provide a safe default configuration, but we advise you to
|
||||
check the options and adjust them as you see fit.
|
||||
|
||||
## Basic installation
|
||||
|
||||
### Requirements
|
||||
|
||||
- PHP version 5.3 or above
|
||||
- _one_ of the following sources of cryptographically safe randomness is required:
|
||||
- PHP 7 or higher
|
||||
- [Libsodium](https://download.libsodium.org/libsodium/content/installation/) and it's [PHP extension](https://paragonie.com/book/pecl-libsodium/read/00-intro.md#installing-libsodium)
|
||||
- open_basedir access to `/dev/urandom`
|
||||
- mcrypt extension
|
||||
- com_dotnet extension
|
||||
|
||||
Mcrypt needs to be able to access `/dev/urandom`. This means if `open_basedir` is set, it must include this file.
|
||||
- GD extension
|
||||
- some disk space or (optional) a database supported by [PDO](https://secure.php.net/manual/book.pdo.php)
|
||||
- ability to create files and folders in the installation directory and the PATH
|
||||
- A web browser with javascript support
|
||||
|
||||
### Configuration
|
||||
|
||||
In the file `cfg/conf.ini` you can configure PrivateBin. A `cfg/conf.ini.sample`
|
||||
is provided containing all options and default values. You can copy it to
|
||||
`cfg/conf.ini` and adapt it as needed. The config file is divided into multiple
|
||||
sections, which are enclosed in square brackets.
|
||||
|
||||
In the `[main]` section you can enable or disable the discussion feature, set
|
||||
the limit of stored pastes and comments in bytes. The `[traffic]` section lets
|
||||
you set a time limit in seconds. Users may not post more often then this limit
|
||||
to your PrivateBin installation.
|
||||
|
||||
More details can be found in the
|
||||
[configuration documentation](https://github.com/PrivateBin/PrivateBin/wiki/Configuration).
|
||||
|
||||
## Further configuration
|
||||
|
||||
After (or before) setting up PrivateBin, also set up HTTPS, as without HTTPS
|
||||
PrivateBin is not secure. (
|
||||
[More information](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#how-should-i-setup-https))
|
||||
|
||||
If you want to use PrivateBin behind Cloudflare, make sure you disabled Rocket
|
||||
loader and unchecked "Javascript" for Auto Minify, found in your domain settings,
|
||||
under "Speed". (More information
|
||||
[in this FAQ entry](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#user-content-how-to-make-privatebin-work-when-using-cloudflare-for-ddos-protection))
|
||||
|
||||
## Advanced installation
|
||||
|
||||
### Changing the path
|
||||
|
||||
In the index.php you can define a different `PATH`. This is useful to secure your
|
||||
installation. You can move the configuration, data files, templates and PHP
|
||||
libraries (directories cfg, doc, data, lib, tpl, tst and vendor) outside of your
|
||||
document root. This new location must still be accessible to your webserver / PHP
|
||||
process (see also
|
||||
[open_basedir setting](https://secure.php.net/manual/en/ini.core.php#ini.open-basedir)).
|
||||
|
||||
> #### PATH Example
|
||||
> Your PrivateBin installation lives in a subfolder called "paste" inside of
|
||||
> your document root. The URL looks like this:
|
||||
> http://example.com/paste/
|
||||
>
|
||||
> The full path of PrivateBin on your webserver is:
|
||||
> /home/example.com/htdocs/paste
|
||||
>
|
||||
> When setting the path like this:
|
||||
> define('PATH', '../../secret/privatebin/');
|
||||
>
|
||||
> PrivateBin will look for your includes / data here:
|
||||
> /home/example.com/secret/privatebin
|
||||
|
||||
### Web server configuration
|
||||
|
||||
A `robots.txt` file is provided in the root dir of PrivateBin. It disallows all
|
||||
robots from accessing your pastes. It is recommend to place it into the root of
|
||||
your web directory if you have installed PrivateBin in a subdirectory. Make sure
|
||||
to adjust it, so that the file paths match your installation. Of course also
|
||||
adjust the file if you already use a `robots.txt`.
|
||||
|
||||
A `.htaccess.disabled` file is provided in the root dir of PrivateBin. It blocks
|
||||
some known robots and link-scanning bots. If you use Apache, you can rename the
|
||||
file to `.htaccess` to enable this feature. If you use another webserver, you
|
||||
have to configure it manually to do the same.
|
||||
|
||||
### Using a database instead of flat files
|
||||
|
||||
In the configuration file the `[model]` and `[model_options]` sections let you
|
||||
configure your favourite way of storing the pastes and discussions on your
|
||||
server.
|
||||
|
||||
`Filesystem` is the default model, which stores everything in files in the
|
||||
data folder. This is the recommended setup for most sites.
|
||||
|
||||
Under high load, in distributed setups or if you are not allowed to store files
|
||||
locally, you might want to switch to the `Database` model. This lets you
|
||||
store your data in a database. Basically all databases that are supported by
|
||||
[PDO](https://secure.php.net/manual/en/book.pdo.php) may be used. Automatic table
|
||||
creation is provided for `pdo_ibm`, `pdo_informix`, `pdo_mssql`, `pdo_mysql`,
|
||||
`pdo_oci`, `pdo_pgsql` and `pdo_sqlite`. You may want to provide a table prefix,
|
||||
if you have to share the PrivateBin database with another application or you want
|
||||
to use a prefix for
|
||||
[security reasons](https://security.stackexchange.com/questions/119510/is-using-a-db-prefix-for-tables-more-secure).
|
||||
The table prefix option is called `tbl`.
|
||||
|
||||
> #### Note
|
||||
> The `Database` model has only been tested with SQLite, MySQL and PostgreSQL,
|
||||
> although it would not be recommended to use SQLite in a production environment.
|
||||
> If you gain any experience running PrivateBin on other RDBMS, please let us
|
||||
> know.
|
||||
|
||||
For reference or if you want to create the table schema for yourself (replace
|
||||
`prefix_` with your own table prefix and create the table schema with phpMyAdmin
|
||||
or the MYSQL console):
|
||||
|
||||
CREATE TABLE prefix_paste (
|
||||
dataid CHAR(16) NOT NULL,
|
||||
data BLOB,
|
||||
postdate INT,
|
||||
expiredate INT,
|
||||
opendiscussion INT,
|
||||
burnafterreading INT,
|
||||
meta TEXT,
|
||||
attachment MEDIUMBLOB,
|
||||
attachmentname BLOB,
|
||||
PRIMARY KEY (dataid)
|
||||
);
|
||||
|
||||
CREATE TABLE prefix_comment (
|
||||
dataid CHAR(16),
|
||||
pasteid CHAR(16),
|
||||
parentid CHAR(16),
|
||||
data BLOB,
|
||||
nickname BLOB,
|
||||
vizhash BLOB,
|
||||
postdate INT,
|
||||
PRIMARY KEY (dataid)
|
||||
);
|
||||
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.1');
|
@ -1,116 +1,63 @@
|
||||
# [<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)
|
||||
|
||||
*Current version: 1.1*
|
||||
|
||||
**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 256bit AES in [Galois Counter mode](https://en.wikipedia.org/wiki/Galois/Counter_Mode).
|
||||
|
||||
This is a fork of ZeroBin, originally developed by
|
||||
[Sébastien Sauvage](https://github.com/sebsauvage/ZeroBin). It was refactored
|
||||
to allow easier and cleaner extensions and has now much more features than the
|
||||
original. It is however still fully compatible to the original ZeroBin 0.19
|
||||
data storage scheme. Therefore such installations can be upgraded to this fork
|
||||
without loosing any data.
|
||||
|
||||
## What PrivateBin provides
|
||||
|
||||
+ As a server administrator you don't have to worry if your users post content
|
||||
that is considered illegal in your country. You have no knowledge of any
|
||||
of the pastes content. If requested or enforced, you can delete any paste from
|
||||
your system.
|
||||
|
||||
+ Pastebin-like system to store text documents, code samples, etc.
|
||||
|
||||
+ Encryption of data sent to server.
|
||||
|
||||
+ Possibility to set a password which is required to read the paste. It further
|
||||
protects a paste and prevents people stumbling upon your paste's link
|
||||
from being able to read it without the password.
|
||||
|
||||
## What it doesn't provide
|
||||
|
||||
- As a user you have to trust the server administrator, your internet provider
|
||||
and any country the traffic passes not to inject any malicious javascript code.
|
||||
For a basic security the PrivateBin installation *has to provide HTTPS*!
|
||||
Additionally it should be secured by
|
||||
[HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) and
|
||||
ideally by [HPKP](https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning) using a
|
||||
certificate either validated by a trusted third party (check the certificate
|
||||
when first using a new PrivateBin instance) or self-signed by the server
|
||||
operator, validated using a
|
||||
[DNSSEC](https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions)
|
||||
protected
|
||||
[DANE](https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities)
|
||||
record.
|
||||
|
||||
- The "key" used to encrypt the paste is part of the URL. If you publicly post
|
||||
the URL of a paste that is not password-protected, everybody can read it.
|
||||
Use a password if you want your paste to be private. In this case make sure to
|
||||
use a strong password and do only share it privately and end-to-end-encrypted.
|
||||
|
||||
- A server admin might be forced to hand over access logs to the authorities.
|
||||
PrivateBin encrypts your text and the discussion contents, but who accessed it
|
||||
first might still be disclosed via such access logs.
|
||||
|
||||
- In case of a server breach your data is secure as it is only stored encrypted
|
||||
on the server. However the server could be misused or the server admin could
|
||||
be legally forced into sending malicious JavaScript to all web users, which
|
||||
grabs the decryption key and send it to the server when a user accesses a
|
||||
PrivateBin.
|
||||
Therefore do not access any PrivateBin instance if you think it has been
|
||||
compromised. As long as no user accesses this instance with a previously
|
||||
generated URL, the content can''t be decrypted.
|
||||
|
||||
## Options
|
||||
|
||||
Some features are optional and can be enabled or disabled in the [configuration
|
||||
file](https://github.com/PrivateBin/PrivateBin/wiki/Configuration):
|
||||
|
||||
* Password protection
|
||||
|
||||
* Discussions, anonymous or with nicknames and IP based identicons or vizhashes
|
||||
|
||||
* Expiration times, including a "forever" and "burn after reading" option
|
||||
|
||||
* Markdown format support for HTML formatted pastes, including preview function
|
||||
|
||||
* Syntax highlighting for source code using prettify.js, including 4 prettify
|
||||
themes
|
||||
|
||||
* File upload support, images get displayed (disabled by default, possibility
|
||||
to adjust size limit)
|
||||
|
||||
* Templates: By default there are bootstrap CSS, darkstrap and "classic ZeroBin"
|
||||
themes and it is easy to adapt these to your own websites layout or create
|
||||
your own.
|
||||
|
||||
* Translation system and automatic browser language detection (if enabled in
|
||||
browser)
|
||||
|
||||
* Language selection (disabled by default, as it uses a session cookie)
|
||||
|
||||
## Further resources
|
||||
|
||||
* [Installation guide](https://github.com/PrivateBin/PrivateBin/wiki/Installation)
|
||||
|
||||
* [Upgrading from ZeroBin 0.19 Alpha](https://github.com/PrivateBin/PrivateBin/wiki/Upgrading-from-ZeroBin-0.19-Alpha)
|
||||
|
||||
* [Configuration guide](https://github.com/PrivateBin/PrivateBin/wiki/Configuration)
|
||||
|
||||
* [Templates](https://github.com/PrivateBin/PrivateBin/wiki/Templates)
|
||||
|
||||
* [Translation guide](https://github.com/PrivateBin/PrivateBin/wiki/Translation)
|
||||
|
||||
* [Developer guide](https://github.com/PrivateBin/PrivateBin/wiki/Development)
|
||||
|
||||
Run into any issues? Have ideas for further developments? Please
|
||||
[report](https://github.com/PrivateBin/PrivateBin/issues) them!
|
||||
# PrivateBin in docker
|
||||
|
||||
## docker-compose.yml example
|
||||
|
||||
This will automatically populate the data under the /srv/data/privatebin/html and /srv/data/privatebin/nginx directories.
|
||||
|
||||
Make sure to create these directories first.
|
||||
|
||||
```
|
||||
version: '3.3'
|
||||
|
||||
services:
|
||||
privatebin-fpm:
|
||||
image: yourrepo/privatebin:1.3.4
|
||||
restart: always
|
||||
networks:
|
||||
- backend
|
||||
volumes:
|
||||
- privatebin_html:/var/www
|
||||
- privatebin_nginx:/etc/nginx/conf.d
|
||||
|
||||
privatebin-nginx:
|
||||
image: nginx:mainline-alpine
|
||||
restart: always
|
||||
networks:
|
||||
- backend
|
||||
volumes:
|
||||
- privatebin_html:/var/www
|
||||
- privatebin_nginx:/etc/nginx/conf.d
|
||||
- /srv/data/privatebin/data:/srv/data
|
||||
depends_on:
|
||||
- privatebin-fpm
|
||||
# add whatever lables/directives you need to expose your nginx container
|
||||
|
||||
volumes:
|
||||
privatebin_html:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
device: /srv/data/privatebin/html
|
||||
o: bind
|
||||
|
||||
privatebin_nginx:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
device: /srv/data/privatebin/nginx
|
||||
o: bind
|
||||
```
|
||||
|
||||
## updating the image
|
||||
|
||||
Update and reset the containers
|
||||
|
||||
```
|
||||
docker-compose stop privatebin-fpm privatebin-nginx
|
||||
docker-compose rm -f privatebin-fpm privatebin-nginx
|
||||
docker volume rm srv_privatebin_html srv_privatebin_nginx
|
||||
rm -rf /srv/data/privatebin/{html,nginx}
|
||||
mkdir -p /srv/data/privatebin/{html,nginx}
|
||||
docker pull yourrepo/privatebin:1.3.4
|
||||
docker-compose up -d
|
||||
```
|
||||
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="img/mstile-150x150.png"/>
|
||||
<square310x310logo src="img/mstile-310x310.png"/>
|
||||
<wide310x150logo src="img/mstile-310x150.png"/>
|
||||
<TileColor>#ffc40d</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
@ -1 +0,0 @@
|
||||
/conf.ini
|
@ -1,2 +0,0 @@
|
||||
Allow from none
|
||||
Deny from all
|
@ -1,152 +0,0 @@
|
||||
; config file for PrivateBin
|
||||
;
|
||||
; An explanation of each setting can be find online at https://github.com/PrivateBin/PrivateBin/wiki/Configuration.
|
||||
|
||||
[main]
|
||||
; (optional) set a project name to be displayed on the website
|
||||
; name = "PrivateBin"
|
||||
|
||||
; enable or disable the discussion feature, defaults to true
|
||||
discussion = true
|
||||
|
||||
; preselect the discussion feature, defaults to false
|
||||
opendiscussion = false
|
||||
|
||||
; enable or disable the password feature, defaults to true
|
||||
password = true
|
||||
|
||||
; enable or disable the file upload feature, defaults to false
|
||||
fileupload = false
|
||||
|
||||
; preselect the burn-after-reading feature, defaults to false
|
||||
burnafterreadingselected = false
|
||||
|
||||
; which display mode to preselect by default, defaults to "plaintext"
|
||||
; make sure the value exists in [formatter_options]
|
||||
defaultformatter = "plaintext"
|
||||
|
||||
; (optional) set a syntax highlighting theme, as found in css/prettify/
|
||||
; syntaxhighlightingtheme = "sons-of-obsidian"
|
||||
|
||||
; size limit per paste or comment in bytes, defaults to 2 Mebibytes
|
||||
sizelimit = 2097152
|
||||
|
||||
; template to include, default is "bootstrap" (tpl/bootstrap.php)
|
||||
template = "bootstrap"
|
||||
|
||||
; (optional) notice to display
|
||||
; notice = "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service."
|
||||
|
||||
; by default PrivateBin will guess the visitors language based on the browsers
|
||||
; settings. Optionally you can enable the language selection menu, which uses
|
||||
; a session cookie to store the choice until the browser is closed.
|
||||
languageselection = false
|
||||
|
||||
; set the language your installs defaults to, defaults to English
|
||||
; if this is set and language selection is disabled, this will be the only language
|
||||
; languagedefault = "en"
|
||||
|
||||
; (optional) URL shortener address to offer after a new paste is created
|
||||
; it is suggested to only use this with self-hosted shorteners as this will leak
|
||||
; the pastes encryption key
|
||||
; urlshortener = "https://shortener.example.com/api?link="
|
||||
|
||||
; (optional) IP based icons are a weak mechanism to detect if a comment was from
|
||||
; a different user when the same username was used in a comment. It might be
|
||||
; used to get the IP of a non anonymous comment poster if the server salt is
|
||||
; leaked and a SHA256 HMAC rainbow table is generated for all (relevant) IPs.
|
||||
; Can be set to one these values: none / vizhash / identicon (default).
|
||||
; icon = none
|
||||
|
||||
; Content Security Policy headers allow a website to restrict what sources are
|
||||
; allowed to be accessed in its context. You need to change this if you added
|
||||
; custom scripts from third-party domains to your templates, e.g. tracking
|
||||
; scripts or run your site behind certain DDoS-protection services.
|
||||
; Check the documentation at https://content-security-policy.com/
|
||||
; Note: If you use a bootstrap theme, you can remove the allow-popups from the sandbox restrictions.
|
||||
; cspheader = "default-src 'none'; manifest-src 'self'; connect-src *; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; referrer no-referrer; sandbox allow-same-origin allow-scripts allow-forms allow-popups"
|
||||
|
||||
; stay compatible with PrivateBin Alpha 0.19, less secure
|
||||
; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of
|
||||
; sha256 in HMAC for the deletion token
|
||||
zerobincompatibility = false
|
||||
|
||||
[expire]
|
||||
; expire value that is selected per default
|
||||
; make sure the value exists in [expire_options]
|
||||
default = "1week"
|
||||
|
||||
; optionally the "clone" button can be disabled on expiring pastes
|
||||
; note that this only hides the button, copy & paste is still possible
|
||||
; clone = false
|
||||
|
||||
[expire_options]
|
||||
; Set each one of these to the number of seconds in the expiration period,
|
||||
; or 0 if it should never expire
|
||||
5min = 300
|
||||
10min = 600
|
||||
1hour = 3600
|
||||
1day = 86400
|
||||
1week = 604800
|
||||
; Well this is not *exactly* one month, it's 30 days:
|
||||
1month = 2592000
|
||||
1year = 31536000
|
||||
never = 0
|
||||
|
||||
[formatter_options]
|
||||
; Set available formatters, their order and their labels
|
||||
plaintext = "Plain Text"
|
||||
syntaxhighlighting = "Source Code"
|
||||
markdown = "Markdown"
|
||||
|
||||
[traffic]
|
||||
; time limit between calls from the same IP address in seconds
|
||||
; Set this to 0 to disable rate limiting.
|
||||
limit = 10
|
||||
|
||||
; (optional) if your website runs behind a reverse proxy or load balancer,
|
||||
; set the HTTP header containing the visitors IP address, i.e. X_FORWARDED_FOR
|
||||
; header = "X_FORWARDED_FOR"
|
||||
|
||||
; directory to store the traffic limits in
|
||||
dir = PATH "data"
|
||||
|
||||
[purge]
|
||||
; minimum time limit between two purgings of expired pastes, it is only
|
||||
; triggered when pastes are created
|
||||
; Set this to 0 to run a purge every time a paste is created.
|
||||
limit = 300
|
||||
|
||||
; maximum amount of expired pastes to delete in one purge
|
||||
; Set this to 0 to disable purging. Set it higher, if you are running a large
|
||||
; site
|
||||
batchsize = 10
|
||||
|
||||
; directory to store the purge limit in
|
||||
dir = PATH "data"
|
||||
|
||||
[model]
|
||||
; name of data model class to load and directory for storage
|
||||
; the default model "Filesystem" stores everything in the filesystem
|
||||
class = Filesystem
|
||||
[model_options]
|
||||
dir = PATH "data"
|
||||
|
||||
;[model]
|
||||
; example of DB configuration for MySQL
|
||||
;class = Database
|
||||
;[model_options]
|
||||
;dsn = "mysql:host=localhost;dbname=privatebin;charset=UTF8"
|
||||
;tbl = "privatebin_" ; table prefix
|
||||
;usr = "privatebin"
|
||||
;pwd = "Z3r0P4ss"
|
||||
;opt[12] = true ; PDO::ATTR_PERSISTENT
|
||||
|
||||
;[model]
|
||||
; example of DB configuration for SQLite
|
||||
;class = Database
|
||||
;[model_options]
|
||||
;dsn = "sqlite:" PATH "data/db.sq3"
|
||||
;usr = null
|
||||
;pwd = null
|
||||
;opt[12] = true ; PDO::ATTR_PERSISTENT
|
@ -1,38 +0,0 @@
|
||||
{
|
||||
"name": "privatebin/privatebin",
|
||||
"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).",
|
||||
"type": "project",
|
||||
"keywords": ["private", "secure", "end-to-end-encrypted", "e2e", "paste", "pastebin", "zero", "zero-knowledge", "encryption", "encrypted", "AES"],
|
||||
"homepage": "https://github.com/PrivateBin",
|
||||
"license":"zlib-acknowledgement",
|
||||
"support": {
|
||||
"issues": "https://github.com/PrivateBin/PrivateBin/issues",
|
||||
"wiki": "https://github.com/PrivateBin/PrivateBin/wiki",
|
||||
"source": "https://github.com/PrivateBin/PrivateBin",
|
||||
"docs": "https://zerobin.dssr.ch/documentation/"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/PrivateBin/PrivateBin"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^5.3.0 || ^7.0",
|
||||
"paragonie/random_compat": "2.0.4",
|
||||
"yzalis/identicon": "1.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"codacy/coverage": "dev-master",
|
||||
"codeclimate/php-test-reporter": "dev-master",
|
||||
"giorgiosironi/eris": "dev-master"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PrivateBin\\": "lib/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"autoloader-suffix": "DontChange"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 106 KiB |
@ -1,113 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
body {
|
||||
padding: 0 0 30px;
|
||||
}
|
||||
|
||||
body.navbar-spacing {
|
||||
padding-top: 70px;
|
||||
}
|
||||
|
||||
.buttondisabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.navbar-nav {
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
.nav.navbar-nav > li {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding: 6px 4px 0 8px;
|
||||
}
|
||||
|
||||
.navbar-form {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > label, .dropdown-menu > li > div {
|
||||
clear: both;
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
line-height: 1.42857;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > label {
|
||||
color: #333;
|
||||
padding: 3px 20px 3px 40px;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > div {
|
||||
color: #777;
|
||||
padding: 3px 20px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pull-right .dropdown-menu {
|
||||
margin-left: -5em;
|
||||
}
|
||||
|
||||
#language {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
#image img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#deletelink {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#pastelink {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#pastelink > a {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#preview {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#message {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#nickname {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
#comments, #comments button {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.comment {
|
||||
border-left: 1px solid #ccc;
|
||||
padding: 5px 0 5px 10px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
footer h4 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 {
|
||||
list-style-type: decimal !important;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
/**
|
||||
* PrivateBin
|
||||
*
|
||||
* CSS file only loaded when no JavaScript available.
|
||||
*
|
||||
* @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.0
|
||||
*/
|
||||
|
||||
/* When there is no script at all other */
|
||||
.noscript-hide {
|
||||
display: none;
|
||||
}
|
@ -1 +0,0 @@
|
||||
pre.prettyprint{display:block;background-color:#333}pre .nocode{background-color:none;color:#000}pre .str{color:#ffa0a0}pre .kwd{color:#f0e68c;font-weight:bold}pre .com{color:#87ceeb}pre .typ{color:#98fb98}pre .lit{color:#cd5c5c}pre .pun{color:#fff}pre .pln{color:#fff}pre .tag{color:#f0e68c;font-weight:bold}pre .atn{color:#bdb76b;font-weight:bold}pre .atv{color:#ffa0a0}pre .dec{color:#98fb98}ol.linenums{margin-top:0;margin-bottom:0;color:#aeaeae}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{pre.prettyprint{background-color:none}pre .str,code .str{color:#060}pre .kwd,code .kwd{color:#006;font-weight:bold}pre .com,code .com{color:#600;font-style:italic}pre .typ,code .typ{color:#404;font-weight:bold}pre .lit,code .lit{color:#044}pre .pun,code .pun{color:#440}pre .pln,code .pln{color:#000}pre .tag,code .tag{color:#006;font-weight:bold}pre .atn,code .atn{color:#404}pre .atv,code .atv{color:#060}}
|
@ -1 +0,0 @@
|
||||
pre .str,code .str{color:#fec243}pre .kwd,code .kwd{color:#8470ff}pre .com,code .com{color:#32cd32;font-style:italic}pre .typ,code .typ{color:#6ecbcc}pre .lit,code .lit{color:#d06}pre .pun,code .pun{color:#8b8970}pre .pln,code .pln{color:#f0f0f0}pre .tag,code .tag{color:#9c9cff}pre .htm,code .htm{color:#dda0dd}pre .xsl,code .xsl{color:#d0a0d0}pre .atn,code .atn{color:#46eeee;font-weight:normal}pre .atv,code .atv{color:#eeb4b4}pre .dec,code .dec{color:#3387cc}a{text-decoration:none}pre.prettyprint,code.prettyprint{font-family:'Droid Sans Mono','CPMono_v07 Bold','Droid Sans';font-weight:bold;font-size:9pt;background-color:#0f0f0f;-moz-border-radius:8px;-webkit-border-radius:8px;-o-border-radius:8px;-ms-border-radius:8px;-khtml-border-radius:8px;border-radius:8px}pre.prettyprint{width:95%;margin:1em auto;padding:1em;white-space:pre-wrap}pre.prettyprint a,code.prettyprint a{text-decoration:none}ol.linenums{margin-top:0;margin-bottom:0;color:#8b8970}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{pre.prettyprint,code.prettyprint{background-color:#fff}pre .str,code .str{color:#088}pre .kwd,code .kwd{color:#006;font-weight:bold}pre .com,code .com{color:#0c3;font-style:italic}pre .typ,code .typ{color:#404;font-weight:bold}pre .lit,code .lit{color:#044}pre .pun,code .pun{color:#440}pre .pln,code .pln{color:#000}pre .tag,code .tag{color:#b66ff7;font-weight:bold}pre .htm,code .htm{color:#606;font-weight:bold}pre .xsl,code .xsl{color:#606;font-weight:bold}pre .atn,code .atn{color:#c71585;font-weight:normal}pre .atv,code .atv{color:#088;font-weight:normal}}
|
@ -1 +0,0 @@
|
||||
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
|
@ -1 +0,0 @@
|
||||
.str{color:#ec7600}.kwd{color:#93c763}.com{color:#66747b}.typ{color:#678cb1}.lit{color:#facd22}.pun{color:#f1f2f3}.pln{color:#f1f2f3}.tag{color:#8ac763}.atn{color:#e0e2e4}.atv{color:#ec7600}.dec{color:purple}pre.prettyprint{border:0 solid #888}ol.linenums{margin-top:0;margin-bottom:0}.prettyprint{background:#000}li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9{color:#555;list-style-type:decimal}li.L1,li.L3,li.L5,li.L7,li.L9{background:#111}@media print{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun{color:#440}.pln{color:#000}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}
|
@ -1 +0,0 @@
|
||||
pre .str,code .str{color:#65b042}pre .kwd,code .kwd{color:#e28964}pre .com,code .com{color:#aeaeae;font-style:italic}pre .typ,code .typ{color:#89bdff}pre .lit,code .lit{color:#3387cc}pre .pun,code .pun{color:#fff}pre .pln,code .pln{color:#fff}pre .tag,code .tag{color:#89bdff}pre .atn,code .atn{color:#bdb76b}pre .atv,code .atv{color:#65b042}pre .dec,code .dec{color:#3387cc}pre.prettyprint,code.prettyprint{background-color:#000;-moz-border-radius:8px;-webkit-border-radius:8px;-o-border-radius:8px;-ms-border-radius:8px;-khtml-border-radius:8px;border-radius:8px}pre.prettyprint{width:95%;margin:1em auto;padding:1em;white-space:pre-wrap}ol.linenums{margin-top:0;margin-bottom:0;color:#aeaeae}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{pre .str,code .str{color:#060}pre .kwd,code .kwd{color:#006;font-weight:bold}pre .com,code .com{color:#600;font-style:italic}pre .typ,code .typ{color:#404;font-weight:bold}pre .lit,code .lit{color:#044}pre .pun,code .pun{color:#440}pre .pln,code .pln{color:#000}pre .tag,code .tag{color:#006;font-weight:bold}pre .atn,code .atn{color:#404}pre .atv,code .atv{color:#060}}
|
@ -1,445 +0,0 @@
|
||||
/**
|
||||
* PrivateBin
|
||||
*
|
||||
* Main CSS file.
|
||||
*
|
||||
* @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.1
|
||||
*/
|
||||
|
||||
/* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.
|
||||
Licensed under the BSD License. - http://yuilibrary.com/license/ */
|
||||
html{color:#000;background:#fff}body,div,dl,dt,dd,ul,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit}input,textarea,select{font-size:100%;}legend{color:#000}
|
||||
|
||||
html {
|
||||
background-color: #455463;
|
||||
color: #fff;
|
||||
min-height: 100%;
|
||||
background-image: linear-gradient(bottom, #0f1823 0, #455463 100%);
|
||||
background-image: -o-linear-gradient(bottom, #0f1823 0, #455463 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #0f1823 0, #455463 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #0f1823 0, #455463 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #0f1823 0, #455463 100%);
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #0f1823), color-stop(1, #455463));
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 15px;
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
}
|
||||
|
||||
a { color: #0f388f; cursor:pointer; }
|
||||
|
||||
h1.title {
|
||||
font-size: 3.5em;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
position: relative;
|
||||
display: inline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
h1.title:before {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
color: rgba(255,255,255,0.15);
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
h2.title {
|
||||
color: #000;
|
||||
font-size: 1em;
|
||||
display: inline;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
bottom: 8px;
|
||||
}
|
||||
|
||||
h3.title {
|
||||
color: #94a3b4;
|
||||
font-size: 0.7em;
|
||||
display: inline;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
bottom: 8px;
|
||||
}
|
||||
|
||||
#aboutbox {
|
||||
color: #94a3b4;
|
||||
padding: 4px 8px 4px 16px;
|
||||
position: relative;
|
||||
top: 10px;
|
||||
border-left: 2px solid #94a3b4;
|
||||
float: right;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
#aboutbox a { color: #94a3b4; }
|
||||
|
||||
#message, #cleartext, #prettymessage, #attachment, .replymessage {
|
||||
clear: both;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
font-size: 9pt;
|
||||
border: 1px solid #28343F;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
-o-box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#message, .replymessage {
|
||||
padding: 5px;
|
||||
white-space: pre-wrap;
|
||||
font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace;
|
||||
}
|
||||
|
||||
#image img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#status {
|
||||
clear: both;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
#pasteresult {
|
||||
background-color: #1F2833;
|
||||
color: #fff;
|
||||
padding: 4px 12px;
|
||||
clear: both;
|
||||
-moz-box-shadow: inset 0 2px 2px #000;
|
||||
-webkit-box-shadow: inset 0 2px 2px #000;
|
||||
box-shadow: inset 0 2px 2px #000;
|
||||
}
|
||||
|
||||
#pasteresult a { color: #fff; }
|
||||
|
||||
#pasteresult button { margin-left: 11px; }
|
||||
|
||||
#deletelink { float: right; }
|
||||
|
||||
#toolbar, #status { margin-bottom: 5px; }
|
||||
|
||||
#copyhint { color: #666; font-size: 0.85em; }
|
||||
|
||||
button, .button {
|
||||
color: #fff;
|
||||
background-color: #323b47;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center left;
|
||||
padding: 4px 8px;
|
||||
font-size: 1em;
|
||||
margin-right: 5px;
|
||||
display: inline-block;
|
||||
background-image: linear-gradient(bottom, #323b47 0, #51606e 100%);
|
||||
background-image: -o-linear-gradient(bottom, #323b47 0, #51606e 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #323b47 0, #51606e 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #323b47 0, #51606e 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #323b47 0, #51606e 100%);
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #323b47), color-stop(1, #51606e));
|
||||
border: 1px solid #28343F;
|
||||
-moz-box-shadow: inset 0 1px 2px #647384;
|
||||
-webkit-box-shadow: inset 0 1px 2px #647384;
|
||||
box-shadow: inset 0 1px 2px #647384;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-background-clip: padding;
|
||||
-webkit-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-image: linear-gradient(bottom, #424b57 0%, #61707e 100%);
|
||||
background-image: -o-linear-gradient(bottom, #424b57 0%, #61707e 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #424b57 0%, #61707e 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #424b57 0%, #61707e 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #424b57 0%, #61707e 100%);
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #424b57), color-stop(1, #61707e));
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-image: linear-gradient(bottom, #51606e 0, #323b47 100%);
|
||||
background-image: -o-linear-gradient(bottom, #51606e 0, #323b47 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #51606e 0, #323b47 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #51606e 0, #323b47 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #51606e 0, #323b47 100%);
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #51606e), color-stop(1, #323b47));
|
||||
position:relative;
|
||||
top:1px;
|
||||
}
|
||||
|
||||
button:disabled, .buttondisabled {
|
||||
background: #ccc;
|
||||
color: #888;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
button img {
|
||||
margin-right: 8px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: #414d5a;
|
||||
padding: 6px 8px;
|
||||
margin: 0 5px 0 0;
|
||||
position: relative;
|
||||
bottom: 1px; /* WTF ? Why is this shifted by 1 pixel ? */
|
||||
}
|
||||
|
||||
.button select {
|
||||
color: #eee;
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
.button select option {
|
||||
color:#eee;
|
||||
background: #414d5a;
|
||||
}
|
||||
|
||||
#rawtextbutton img {
|
||||
padding: 1px 0 1px 0;
|
||||
}
|
||||
|
||||
#remainingtime, #password {
|
||||
color: #94a3b4;
|
||||
display: inline;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
#newbutton {
|
||||
float: right;
|
||||
margin-right: 0;
|
||||
margin-bottom: 5px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
input {
|
||||
color: #777;
|
||||
font-size: 1em;
|
||||
padding: 6px;
|
||||
border: 1px solid #28343f;
|
||||
}
|
||||
|
||||
.blink {
|
||||
text-decoration: blink;
|
||||
font-size: 0.8em;
|
||||
color: #a4b3c4;
|
||||
}
|
||||
|
||||
.foryoureyesonly {
|
||||
color: #ff0 !important;
|
||||
font-size: 1em !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
#image, .nonworking {
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 10pt;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.hidden { display: none !important; }
|
||||
|
||||
#ienotice {
|
||||
background-color: #7e98af;
|
||||
color: #000;
|
||||
font-size: 0.85em;
|
||||
padding: 3px 5px;
|
||||
text-align: center;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#ienotice a { color: #000; }
|
||||
|
||||
#oldienotice { display: none; }
|
||||
|
||||
.errorMessage {
|
||||
background-color: #f77 !important;
|
||||
color:#ff0;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/* --- discussion related CSS ------- */
|
||||
|
||||
#discussion { /* Discussion container */
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
margin-left: -30px;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
h4.title {
|
||||
font-size: 1.2em;
|
||||
color: #94a3b4;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.comment /* One single reply */
|
||||
{
|
||||
background-color: #ceced6;
|
||||
color: #000;
|
||||
white-space: pre-wrap;
|
||||
font-family: Consolas,"Lucida Console","DejaVu Sans Mono",Monaco,monospace;
|
||||
font-size: 9pt;
|
||||
border-left: 1px solid #859AAE;
|
||||
border-top: 1px solid #859AAE;
|
||||
padding: 5px 0px 5px 5px;
|
||||
margin-left: 30px;
|
||||
-moz-box-shadow: -3px -3px 5px rgba(0,0,0,0.15);
|
||||
-webkit-box-shadow: -3px -3px 5px rgba(0,0,0,0.15);
|
||||
box-shadow: -3px -3px 5px rgba(0,0,0,0.15);
|
||||
min-width: 200px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.reply { margin: 5px 0 0 30px; }
|
||||
|
||||
#replystatus {
|
||||
display: inline;
|
||||
padding: 1px 7px;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.comment button {
|
||||
color: #446;
|
||||
background-color: #aab;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center left;
|
||||
padding: 0 2px;
|
||||
font-size: 0.73em;
|
||||
margin: 3px 5px 3px 0;
|
||||
display: inline;
|
||||
background-image: linear-gradient(bottom, #aab 0, #ccc 100%);
|
||||
background-image: -o-linear-gradient(bottom, #aab 0, #ccc 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #aab 0, #ccc 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #aab 0, #ccc 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #aab 0, #ccc 100%);
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #aab), color-stop(1, #ccc));
|
||||
border: 1px solid #ccd;
|
||||
-moz-box-shadow: inset 0 1px 2px #ddd;
|
||||
-webkit-box-shadow: inset 0 1px 2px #fff;
|
||||
box-shadow: inset 0 1px 2px #eee;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-background-clip: padding;
|
||||
-webkit-background-clip: padding-box;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
.comment button:hover {
|
||||
background-image: linear-gradient(bottom, #ccd 0, #fff 100%);
|
||||
background-image: -o-linear-gradient(bottom, #ccd 0, #fff 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #ccd 0, #fff 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #ccd 0, #fff 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #ccd 0, #fff 100%);
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccd), color-stop(1, #fff));
|
||||
}
|
||||
|
||||
.comment button:active {
|
||||
background-image: linear-gradient(bottom, #fff 0, #889 100%);
|
||||
background-image: -o-linear-gradient(bottom, #fff 0, #889 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #fff 0, #889 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #fff 0, #889 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #fff 0, #889 100%);
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(1, #889));
|
||||
position:relative;
|
||||
top:1px;
|
||||
}
|
||||
|
||||
.comment input { padding: 2px; }
|
||||
|
||||
#replymessage { margin-top: 5px; }
|
||||
|
||||
.commentmeta {
|
||||
color: #fff;
|
||||
background-color: #8ea0b2;
|
||||
margin-bottom: 3px;
|
||||
padding: 0 0 0 3px;
|
||||
}
|
||||
|
||||
.commentdate { color: #bfcede; }
|
||||
|
||||
img.vizhash {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
left: -3px;
|
||||
}
|
||||
|
||||
#prettyprint {
|
||||
color: #000000;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#prettyprint.prettyprinted {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#cleartext {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#cleartext * {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#cleartext ol {
|
||||
list-style: auto;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#cleartext ul {
|
||||
list-style: disc;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#cleartext h1, #cleartext h2, #cleartext h3, #cleartext h4, #cleartext h5, #cleartext h6 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#cleartext h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
#cleartext h2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
#cleartext h3 {
|
||||
font-size: 1.2em;
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
Generating PHP documentation
|
||||
============================
|
||||
|
||||
In order to generate the documentation, you will need to install the following
|
||||
packages and its dependencies:
|
||||
* phpdoc
|
||||
* graphviz
|
||||
|
||||
Details about
|
||||
[installing phpDocumentor](https://phpdoc.org/docs/latest/getting-started/installing.html)
|
||||
can be found in that projects documentation.
|
||||
|
||||
Example for Debian and Ubuntu:
|
||||
```console
|
||||
$ sudo apt install php-pear graphviz
|
||||
$ sudo pear channel-discover pear.phpdoc.org
|
||||
$ sudo pear install phpdoc/phpDocumentor
|
||||
```
|
||||
|
||||
To generate the documentation, change into the main directory and run phpdoc:
|
||||
```console
|
||||
$ cd PrivateBin
|
||||
$ phpdoc -t doc/phpdoc -d lib/
|
||||
```
|
||||
|
||||
**Note:** When used with PHP 7, the prerelease of phpDocumentator 2.9 needs to be
|
||||
manually installed by downloading it from
|
||||
[GitHub](https://github.com/phpDocumentor/phpDocumentor2/releases/download/v2.9.0/phpDocumentor.phar)
|
||||
and then manually moving it to e.g. `/usr/local/bin` and making it executable.
|
||||
|
||||
Generating JS documentation
|
||||
============================
|
||||
|
||||
In order to generate the documentation, you will need to install the following
|
||||
packages and its dependencies:
|
||||
* npm
|
||||
|
||||
Then you can use the node package manager to install the latest stable release
|
||||
of jsdoc globally:
|
||||
|
||||
```console
|
||||
$ npm install -g jsdoc
|
||||
```
|
||||
|
||||
Example for Debian and Ubuntu, including steps to allow current user to install
|
||||
node modules globally:
|
||||
```console
|
||||
$ sudo apt install npm
|
||||
$ sudo mkdir /usr/local/lib/node_modules
|
||||
$ sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
|
||||
$ npm install -g jsdoc
|
||||
$ ln -s /usr/bin/nodejs /usr/local/bin/node
|
||||
```
|
||||
|
||||
To generate the documentation, change into the main directory and run phpdoc:
|
||||
```console
|
||||
$ cd PrivateBin
|
||||
$ jsdoc -d doc/jsdoc js/privatebin.js
|
||||
```
|
||||
|
@ -0,0 +1,24 @@
|
||||
server {
|
||||
listen 80 default_server;
|
||||
|
||||
root /var/www;
|
||||
index index.php index.html index.htm;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
|
||||
# since I am running in Docker
|
||||
resolver 127.0.0.11 ipv6=off;
|
||||
set $privatebin privatebin-fpm:9000;
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass $privatebin;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
|
||||
# Prevent exposing nginx + version to $_SERVER
|
||||
fastcgi_param SERVER_SOFTWARE "";
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
; session.use_strict_mode specifies whether the module will use strict session id mode. If this
|
||||
; mode is enabled, the module does not accept uninitialized session ID. If uninitialized session ID
|
||||
; is sent from browser, new session ID is sent to browser. Applications are protected from session
|
||||
; fixation via session adoption with strict mode. Defaults to 0 (disabled).
|
||||
session.use_strict_mode=On
|
||||
|
||||
; Enable assert() evaluation.
|
||||
assert.active=Off
|
||||
|
||||
; This determines whether errors should be printed to the screen as part of the output or if they
|
||||
; should be hidden from the user. Value "stderr" sends the errors to stderr instead of stdout.
|
||||
display_errors=Off
|
||||
|
||||
; Tells whether script error messages should be logged to the server's error log or error_log.
|
||||
; You're strongly advised to use error logging in place of error displaying on production web sites.
|
||||
log_errors=On
|
||||
|
||||
|
||||
|
||||
; increase size limits
|
||||
upload_max_filesize=15M
|
||||
post_max_size=15M
|
||||
|
||||
|
||||
|
||||
; best practices
|
||||
|
||||
; Disable deprecated short open tags ("<?")
|
||||
short_open_tag=Off
|
||||
|
||||
; Do not expose php version header
|
||||
expose_php=Off
|
||||
|
||||
; -1 can be used (like E_ALL) to report all errors - including those coming in new php versions
|
||||
error_reporting=-1
|
||||
|
||||
|
||||
|
||||
; performance
|
||||
|
||||
; we want fast cli scripts too
|
||||
opcache.enable_cli=On
|
||||
|
||||
; fast shutdown because we skip free() calls
|
||||
opcache.fast_shutdown=On
|
||||
|
||||
; The amount of memory used to store interned strings, in megabytes
|
||||
opcache.interned_strings_buffer=8
|
||||
|
||||
; The maximum number of keys (and therefore scripts) in the OPcache hash table
|
||||
opcache.max_accelerated_files=20000
|
||||
|
||||
; The size of the shared memory storage used by OPcache, in megabytes
|
||||
opcache.memory_consumption=128
|
||||
|
||||
; If enabled, OPcache will check for updated scripts every opcache.revalidate_freq seconds. When
|
||||
; this directive is disabled, you must reset OPcache manually via opcache_reset(),
|
||||
; opcache_invalidate() or by restarting the Web server for changes to the filesystem to take effect.
|
||||
opcache.validate_timestamps=Off
|
||||
|
||||
; Determines the size of the realpath cache to be used by PHP. This value
|
||||
; should be increased on systems where PHP opens many files, to reflect the
|
||||
; quantity of the file operations performed.
|
||||
realpath_cache_size=4096K
|
@ -0,0 +1,18 @@
|
||||
[global]
|
||||
daemonize = no
|
||||
error_log = /dev/stderr
|
||||
|
||||
[www]
|
||||
user = user
|
||||
group = user
|
||||
listen = 0.0.0.0:9000
|
||||
pm = dynamic
|
||||
pm.max_children = 5
|
||||
pm.start_servers = 2
|
||||
pm.min_spare_servers = 1
|
||||
pm.max_spare_servers = 3
|
||||
clear_env = On
|
||||
;access.log = /dev/null
|
||||
;php_admin_value[upload_max_filesize] = 15M
|
||||
;php_admin_value[post_max_size] = 15M
|
||||
;php_admin_value[output_buffering] = 0
|
@ -1,151 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s ist ein minimalistischer, quelloffener \"Pastebin\"-artiger Dienst, bei dem der Server keinerlei Kenntnis der Inhalte hat. Die Daten werden <i>im Browser</i> mit 256 Bit AES ver- und entschlüsselt. Weitere Informationen sind auf der <a href=\"https://privatebin.info/\">Projektseite</a> zu finden.",
|
||||
"Because ignorance is bliss":
|
||||
"Unwissenheit ist ein Segen",
|
||||
"en": "de",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Diesen Text gibt es nicht, er ist abgelaufen oder wurde gelöscht.",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"%s benötigt PHP 5.3.0 oder höher, um zu funktionieren. Sorry.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s benötigt den Konfigurationsabschnitt [%s] in der Konfigurationsdatei um zu funktionieren.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Bitte warte %d Sekunden zwischen dem Absenden.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Texte sind auf %s verschlüsselte Datenmenge beschränkt.",
|
||||
"Invalid data.":
|
||||
"Ungültige Daten.",
|
||||
"You are unlucky. Try again.":
|
||||
"Du hast Pech. Versuchs nochmal.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Fehler beim Speichern des Kommentars. Sorry.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Fehler beim Speichern des Textes. Sorry.",
|
||||
"Invalid paste ID.":
|
||||
"Ungültige Text-ID.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Text ist kein \"Einmal\"-Typ.",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Falscher Lösch-Code. Text wurde nicht gelöscht.",
|
||||
"Paste was properly deleted.":
|
||||
"Text wurde erfolgreich gelöscht.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"JavaScript ist eine Voraussetzung, um %s zu nutzen.<br />Bitte entschuldige die Unannehmlichkeiten.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s setzt einen modernen Browser voraus, um funktionieren zu können.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Du benutzt immer noch den Internet Explorer? Tu Dir einen Gefallen und wechsle zu einem moderneren Browser:",
|
||||
"New":
|
||||
"Neu",
|
||||
"Send":
|
||||
"Senden",
|
||||
"Clone":
|
||||
"Klonen",
|
||||
"Raw text":
|
||||
"Reiner Text",
|
||||
"Expires":
|
||||
"Ablaufzeit",
|
||||
"Burn after reading":
|
||||
"Einmal-Text",
|
||||
"Open discussion":
|
||||
"Diskussion eröffnen",
|
||||
"Password (recommended)":
|
||||
"Passwort (empfohlen)",
|
||||
"Discussion":
|
||||
"Diskussion",
|
||||
"Toggle navigation":
|
||||
"Navigation umschalten",
|
||||
"%d seconds": ["%d Sekunde", "%d Sekunden"],
|
||||
"%d minutes": ["%d Minute", "%d Minuten"],
|
||||
"%d hours": ["%d Stunde", "%d Stunden"],
|
||||
"%d days": ["%d Tag", "%d Tage"],
|
||||
"%d weeks": ["%d Woche", "%d Wochen"],
|
||||
"%d months": ["%d Monat", "%d Monate"],
|
||||
"%d years": ["%d Jahr", "%d Jahre"],
|
||||
"Never":
|
||||
"Nie",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Hinweis: Dies ist ein Versuchsdienst. Daten können jederzeit gelöscht werden. Kätzchen werden sterben wenn du diesen Dienst missbrauchst.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Dieses Dokument läuft in einer Sekunde ab.", "Dieses Dokument läuft in %d Sekunden ab."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Dieses Dokument läuft in einer Minute ab.", "Dieses Dokument läuft in %d Minuten ab."],
|
||||
"This document will expire in %d hours.":
|
||||
["Dieses Dokument läuft in einer Stunde ab.", "Dieses Dokument läuft in %d Stunden ab."],
|
||||
"This document will expire in %d days.":
|
||||
["Dieses Dokument läuft in einem Tag ab.", "Dieses Dokument läuft in %d Tagen ab."],
|
||||
"This document will expire in %d months.":
|
||||
["Dieses Dokument läuft in einem Monat ab.", "Dieses Dokument läuft in %d Monaten ab."],
|
||||
"Please enter the password for this paste:":
|
||||
"Bitte gib das Passwort für diesen Text ein:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Konnte Daten nicht entschlüsseln (Falscher Schlüssel?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Konnte den Text nicht löschen, er wurde nicht im Einmal-Modus gespeichert.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"DIESER TEXT IST NUR FÜR DICH GEDACHT. Schliesse das Fenster nicht, diese Nachricht kann nur einmal geöffnet werden.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Konnte Kommentar nicht entschlüsseln; Falscher Schlüssel?",
|
||||
"Reply":
|
||||
"Antworten",
|
||||
"Anonymous":
|
||||
"Anonym",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Anonymer Avatar (Vizhash der IP-Addresse)",
|
||||
"Add comment":
|
||||
"Kommentar hinzufügen",
|
||||
"Optional nickname...":
|
||||
"Optionales Pseudonym...",
|
||||
"Post comment":
|
||||
"Kommentar absenden",
|
||||
"Sending comment...":
|
||||
"Sende Kommentar...",
|
||||
"Comment posted.":
|
||||
"Kommentar gesendet.",
|
||||
"Could not refresh display: %s":
|
||||
"Konnte Ansicht nicht aktualisieren: %s",
|
||||
"unknown status":
|
||||
"Unbekannter Grund",
|
||||
"server error or not responding":
|
||||
"Fehler auf dem Server oder keine Antwort vom Server",
|
||||
"Could not post comment: %s":
|
||||
"Konnte Kommentar nicht senden: %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Sende Text (Bitte bewege Deine Maus um die Entropie zu erhöhen)...",
|
||||
"Sending paste...":
|
||||
"Sende Text...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Dein Text ist unter <a id=\"pasteurl\" href=\"%s\">%s</a> zu finden <span id=\"copyhint\">(Drücke [Strg]+[c] um den Link zu kopieren)</span>",
|
||||
"Delete data":
|
||||
"Lösche Daten",
|
||||
"Could not create paste: %s":
|
||||
"Konnte Text nicht erstellen: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Konnte Text nicht entschlüsseln: Der Schlüssel fehlt in der Adresse (Hast du eine Umleitung oder einen URL-Verkürzer benutzt, der Teile der Adresse entfernt?)",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Nur Text",
|
||||
"Source Code": "Quellcode",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Anhang herunterladen",
|
||||
"Cloned file attached.": "Kopierte Datei angehängt.",
|
||||
"Attach a file": "Datei anhängen",
|
||||
"Remove attachment": "Anhang entfernen",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Dein Browser unterstützt das hochladen von verschlüsselten Dateien nicht. Bitte verwende einen neueren Browser.",
|
||||
"Invalid attachment.": "Ungültiger Datei-Anhang.",
|
||||
"Options": "Optionen",
|
||||
"Shorten URL": "URL verkürzen",
|
||||
"Editor": "Bearbeiten",
|
||||
"Preview": "Vorschau",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"Der PATH muss bei %s mit einem \"%s\" enden. Bitte passe Deinen PATH in Deiner index.php an.",
|
||||
"Decrypt":
|
||||
"Entschlüsseln",
|
||||
"Enter password":
|
||||
"Passwort eingeben",
|
||||
"Loading…": "Lädt…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Wenn diese Nachricht nicht mehr verschwindet, schau bitte in <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">die FAQ</a> (englisch), um zu sehen, wie der Fehler behoben werden kann."
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s es un servicio de tipo \"Pastebin\" minimalista de código abierto, donde el servidor no tiene ningún conocimiento de los datos guardados. Los datos son cifrados/descifrados <i>en el navegador</i> usando 256 bits AES. Más información en la <a href=\"https://privatebin.info/\">página del proyecto</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Porque la ignorancia es dicha",
|
||||
"en": "es",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"El texto no existe, ha caducado o ha sido eliminado.",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"%s requiere php 5.3.0 o superior para funcionar. Lo siento.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s requiere que la sección de configuración [% s] esté presente en el archivo de configuración.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Por favor espere %d segundos entre cada publicación.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"El texto está limitado a %s de datos cifrados.",
|
||||
"Invalid data.":
|
||||
"Datos inválidos.",
|
||||
"You are unlucky. Try again.":
|
||||
"Tienes mala suerte. Inténtalo de nuevo",
|
||||
"Error saving comment. Sorry.":
|
||||
"Error al guardar el comentario. Lo siento.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Error al guardar el texto. Lo siento",
|
||||
"Invalid paste ID.":
|
||||
"ID del texto inválido.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"El texto no es del tipo \"destruir despues de leer\".",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Token de eliminación erróneo. El texto no fue eliminado.",
|
||||
"Paste was properly deleted.":
|
||||
"El texto se ha eliminado correctamente.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"JavaScript es necesario para que %s funcione.<br />Sentimos los inconvenientes ocasionados.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s requiere un navegador moderno para funcionar.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"¿Sigues usando Internet Explorer? Hazte un favor, cambia a un navegador moderno:",
|
||||
"New":
|
||||
"Nuevo",
|
||||
"Send":
|
||||
"Enviar",
|
||||
"Clone":
|
||||
"Clonar",
|
||||
"Raw text":
|
||||
"Texto sin formato",
|
||||
"Expires":
|
||||
"Caducar en",
|
||||
"Burn after reading":
|
||||
"Destruir después de leer",
|
||||
"Open discussion":
|
||||
"Discusión abierta",
|
||||
"Password (recommended)":
|
||||
"Contraseña (recomendado)",
|
||||
"Discussion":
|
||||
"Discusión",
|
||||
"Toggle navigation":
|
||||
"Cambiar navegación",
|
||||
"%d seconds": ["%d segundo", "%d segundos"],
|
||||
"%d minutes": ["%d minuto", "%d minutos"],
|
||||
"%d hours": ["%d hora", "%d horas"],
|
||||
"%d days": ["%d día", "%d días"],
|
||||
"%d weeks": ["%d semana", "%d semanas"],
|
||||
"%d months": ["%d mes", "%d meses"],
|
||||
"%d years": ["%d año", "%d años"],
|
||||
"Never":
|
||||
"Nunca",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Nota: Este es un servicio de prueba. Los datos pueden ser eliminados en cualquier momento. Gatitos morirán si se abusa de este servicio.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Este documento caducará en un segundo.", "Este documento caducará en %d segundos."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Este documento caducará en un minuto.", "Este documento caducará en %d minutos."],
|
||||
"This document will expire in %d hours.":
|
||||
["Este documento caducará en una hora.", "Este documento caducará en %d horas."],
|
||||
"This document will expire in %d days.":
|
||||
["Este documento caducará en un día.", "Este documento caducará en %d días."],
|
||||
"This document will expire in %d months.":
|
||||
["Este documento caducará en un mes.", "Este documento caducará en %d meses."],
|
||||
"Please enter the password for this paste:":
|
||||
"Por favor ingrese la contraseña para este documento:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"No fue posible descifrar los datos (¿Clave errónea?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"No fue posible eliminar el documento, no fue guardado en modo \"destruir despues de leer\".",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"SÓLO PARA TUS OJOS. No cierre esta ventana, este mensaje no se puede volver a mostrar.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"No se pudo descifrar el comentario; ¿Llave incorrecta?",
|
||||
"Reply":
|
||||
"Responder",
|
||||
"Anonymous":
|
||||
"Anónimo",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar anónimo (Vizhash de la dirección IP)",
|
||||
"Add comment":
|
||||
"Añadir comentario",
|
||||
"Optional nickname...":
|
||||
"Seudónimo opcional...",
|
||||
"Post comment":
|
||||
"Publicar comentario",
|
||||
"Sending comment...":
|
||||
"Enviando comentario...",
|
||||
"Comment posted.":
|
||||
"Comentario publicado.",
|
||||
"Could not refresh display: %s":
|
||||
"No se pudo actualizar la vista: %s",
|
||||
"unknown status":
|
||||
"Estado desconocido",
|
||||
"server error or not responding":
|
||||
"Error del servidor o el servidor no responde",
|
||||
"Could not post comment: %s":
|
||||
"No fue posible publicar comentario: %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Enviando texto (Por favor, mueva el ratón para mayor entropía)...",
|
||||
"Sending paste...":
|
||||
"Enviando texto...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Su texto está en <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Presione [Ctrl]+[c] para copiar)</span>",
|
||||
"Delete data":
|
||||
"Eliminar datos",
|
||||
"Could not create paste: %s":
|
||||
"No fue posible crear el archivo: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"No es posible descifrar el documento: Falta la clave de descifrado en la URL (¿Utilizó un redirector o un acortador de URL que quite parte de la URL?)",
|
||||
"Format": "Formato",
|
||||
"Plain Text": "Texto sin formato",
|
||||
"Source Code": "Código fuente",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Descargar adjunto",
|
||||
"Cloned file attached.": "Archivo clonado adjunto.",
|
||||
"Attach a file": "Adjuntar archivo",
|
||||
"Remove attachment": "Remover adjunto",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Tu navegador no admite la carga de archivos cifrados. Utilice un navegador más reciente.",
|
||||
"Invalid attachment.": "Adjunto inválido.",
|
||||
"Options": "Opciones",
|
||||
"Shorten URL": "Acortar URL",
|
||||
"Editor": "Editor",
|
||||
"Preview": "Previsualización",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"%s requiere que el PATH termine en \"%s\". Por favor, actualice el PATH en su index.php.",
|
||||
"Decrypt":
|
||||
"Descifrar",
|
||||
"Enter password":
|
||||
"Ingrese contraseña",
|
||||
"Loading…": "Cargando…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"En caso de que este mensaje nunca desaparezca por favor revise <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">este FAQ para obtener información para solucionar problemas</a>."
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s est un 'pastebin' (ou gestionnaire d'extraits de texte et de code source) minimaliste et open source, dans lequel le serveur n'a aucune connaissance des données envoyées. Les données sont chiffrées/déchiffrées <i>dans le navigateur</i> par un chiffrage AES 256 bits. Plus d'informations sur <a href=\"https://privatebin.info/\">la page du projet</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Parce que l'ignorance c'est le bonheur",
|
||||
"en": "fr",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Le paste n'existe pas, a expiré, ou a été supprimé.",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"Désolé, %s nécessite php 5.3.0 ou supérieur pour fonctionner.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s a besoin de la section de configuration [%s] dans le fichier de configuration pour fonctionner.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Merci d'attendre %d secondes entre chaque publication.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Le paste est limité à %s de données chiffrées.",
|
||||
"Invalid data.":
|
||||
"Données invalides.",
|
||||
"You are unlucky. Try again.":
|
||||
"Pas de chance. Essayez encore.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Erreur lors de la sauvegarde du commentaire.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Erreur lors de la sauvegarde du paste. Désolé.",
|
||||
"Invalid paste ID.":
|
||||
"ID du paste invalide.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Le paste n'est pas de type \"Effacer après lecture\".",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Jeton de suppression incorrect. Le paste n'a pas été supprimé.",
|
||||
"Paste was properly deleted.":
|
||||
"Le paste a été correctement supprimé.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"JavaScript est requis pour faire fonctionner %s. <br />Désolé pour cet inconvénient.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s nécessite un navigateur moderne pour fonctionner.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Encore sur Internet Explorer ? Faites-vous une faveur, passez à un navigateur moderne :",
|
||||
"New":
|
||||
"Nouveau",
|
||||
"Send":
|
||||
"Envoyer",
|
||||
"Clone":
|
||||
"Cloner",
|
||||
"Raw text":
|
||||
"Texte brut",
|
||||
"Expires":
|
||||
"Expire",
|
||||
"Burn after reading":
|
||||
"Effacer après lecture",
|
||||
"Open discussion":
|
||||
"Autoriser la discussion",
|
||||
"Password (recommended)":
|
||||
"Mot de passe (recommandé)",
|
||||
"Discussion":
|
||||
"Discussion",
|
||||
"Toggle navigation":
|
||||
"Basculer la navigation",
|
||||
"%d seconds": ["%d seconde", "%d secondes"],
|
||||
"%d minutes": ["%d minute", "%d minutes"],
|
||||
"%d hours": ["%d heure", "%d heures"],
|
||||
"%d days": ["%d jour", "%d jours"],
|
||||
"%d weeks": ["%d semaine", "%d semaines"],
|
||||
"%d months": ["%d mois", "%d mois"],
|
||||
"%d years": ["%d an", "%d ans"],
|
||||
"Never":
|
||||
"Jamais",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Note : Ceci est un service de test : les données peuvent être supprimées à tout moment. Des chatons mourront si vous utilisez ce service de manière abusive.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Ce document expirera dans %d seconde.", "Ce document expirera dans %d secondes."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Ce document expirera dans %d minute.", "Ce document expirera dans %d minutes."],
|
||||
"This document will expire in %d hours.":
|
||||
["Ce document expirera dans %d heure.", "Ce document expirera dans %d heures."],
|
||||
"This document will expire in %d days.":
|
||||
["Ce document expirera dans %d jour.", "Ce document expirera dans %d jours."],
|
||||
"This document will expire in %d months.":
|
||||
["Ce document expirera dans %d mois.", "Ce document expirera dans %d mois."],
|
||||
"Please enter the password for this paste:":
|
||||
"Entrez le mot de passe pour ce paste:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Impossible de déchiffrer les données (mauvaise clé ?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Impossible de supprimer le paste, car il n'a pas été stoclé en mode \"Effacer après lecture\".",
|
||||
"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é ?",
|
||||
"Reply":
|
||||
"Répondre",
|
||||
"Anonymous":
|
||||
"Anonyme",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar anonyme (Vizhash de l'adresse IP)",
|
||||
"Add comment":
|
||||
"Ajouter un commentaire",
|
||||
"Optional nickname...":
|
||||
"Pseudonyme optionnel...",
|
||||
"Post comment":
|
||||
"Poster le commentaire",
|
||||
"Sending comment...":
|
||||
"Envoi du commentaire...",
|
||||
"Comment posted.":
|
||||
"Commentaire posté.",
|
||||
"Could not refresh display: %s":
|
||||
"Impossible de rafraichir l'affichage : %s",
|
||||
"unknown status":
|
||||
"Statut inconnu",
|
||||
"server error or not responding":
|
||||
"Le serveur ne répond pas ou a rencontré une erreur",
|
||||
"Could not post comment: %s":
|
||||
"Impossible de poster le commentaire : %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Envoi du paste (Merci de bouger votre souris pour plus d'entropie)...",
|
||||
"Sending paste...":
|
||||
"Envoi du paste...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Votre paste est disponible à l'adresse <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Appuyez sur [Ctrl]+[c] pour copier)</span>",
|
||||
"Delete data":
|
||||
"Supprimer les données du paste",
|
||||
"Could not create paste: %s":
|
||||
"Impossible de créer le paste : %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Impossible de déchiffrer le paste : Clé de déchiffrage manquante dans l'URL (Avez-vous utilisé un redirecteur ou un site de réduction d'URL qui supprime une partie de l'URL ?)",
|
||||
"B": "o",
|
||||
"KiB": "Kio",
|
||||
"MiB": "Mio",
|
||||
"GiB": "Gio",
|
||||
"TiB": "Tio",
|
||||
"PiB": "Pio",
|
||||
"EiB": "Eio",
|
||||
"ZiB": "Zio",
|
||||
"YiB": "Yio",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Texte brut",
|
||||
"Source Code": "Code source",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Télécharger la pièce jointe",
|
||||
"Cloned file attached.": "Cloner le fichier attaché.",
|
||||
"Attach a file": "Attacher un fichier ",
|
||||
"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.",
|
||||
"Invalid attachment.": "Attachement invalide.",
|
||||
"Options": "Options",
|
||||
"Shorten URL": "Raccourcir URL",
|
||||
"Editor": "Éditer",
|
||||
"Preview": "Prévisualiser",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
|
||||
"Decrypt":
|
||||
"Decrypt",
|
||||
"Enter password":
|
||||
"Entrez le mot de passe",
|
||||
"Loading…": "Loading…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a> (in English)."
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s è un sistema di tipo \"Pastebin\" online, open source, minimalista. Il server non possiede alcuna conoscenza (\"Zero Knowledge\") del contenuto dei dati inviati. I dati sono cifrati/decifrati <i>nel Browser</i> con algoritmo AES a 256 Bit. Per ulteriori informazioni, vedi <a href=\"https://privatebin.info/\">Sito del progetto</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Perché l'ignoranza è una benedizione (Because ignorance is bliss)",
|
||||
"en": "it",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Questo messaggio non esiste, è scaduto o è stato cancellato.",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"%s richiede PHP 5.3.0 o superiore.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s richiede la presenza della sezione [%s] nei file di configurazione.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Attendi per favore %d secondi prima di ciascun invio.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"La dimensione del messaggio è limitata a %s di dati cifrati.",
|
||||
"Invalid data.":
|
||||
"Dati non validi.",
|
||||
"You are unlucky. Try again.":
|
||||
"Riprova, sarai più fortunato.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Errore durante il salvataggio del commento.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Errore durante il salvataggio del messaggio.",
|
||||
"Invalid paste ID.":
|
||||
"ID-Messaggio non valido.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Il messaggio non è di tipo Distruggi-dopo-lettura.",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Codice cancellazione errato. Il messaggio NON è stato cancellato.",
|
||||
"Paste was properly deleted.":
|
||||
"Il messaggio è stato correttamente cancellato.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"%s funziona solo con JavaScript attivo.<br />Ci dispiace per l'inconveniente.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s richiede un browser moderno e aggiornato per funzionare.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Usi ancora Internet Explorer? Ti consigliamo di passare ad un browser più sicuro:",
|
||||
"New":
|
||||
"Nuovo",
|
||||
"Send":
|
||||
"Invia",
|
||||
"Clone":
|
||||
"Clona",
|
||||
"Raw text":
|
||||
"Testo Raw",
|
||||
"Expires":
|
||||
"Scade",
|
||||
"Burn after reading":
|
||||
"Distruggi dopo lettura",
|
||||
"Open discussion":
|
||||
"Apri discussione",
|
||||
"Password (recommended)":
|
||||
"Password (raccomandato)",
|
||||
"Discussion":
|
||||
"Discussione",
|
||||
"Toggle navigation":
|
||||
"Scambia Navigazione",
|
||||
"%d seconds": ["%d secondo", "%d secondi"],
|
||||
"%d minutes": ["%d minuto", "%d minuti"],
|
||||
"%d hours": ["%d ora", "%d ore"],
|
||||
"%d days": ["%d giorno", "%d giorni"],
|
||||
"%d weeks": ["%d settimana", "%d settimane"],
|
||||
"%d months": ["%d mese", "%d mesi"],
|
||||
"%d years": ["%d anno", "%d anni"],
|
||||
"Never":
|
||||
"Mai",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Nota: questo è un servizio di prova, i dati possono essere cancellati in qualsiasi momento. Ti preghiamo di non abusare di questo servizio, grazie.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Questo documento scadrà tra un secondo.", "Questo documento scadrà in %d secondi."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Questo documento scadrà tra un minuto.", "Questo documento scadrà in %d minuti."],
|
||||
"This document will expire in %d hours.":
|
||||
["Questo documento scadrà tra un'ora.", "Questo documento scadrà in %d ore."],
|
||||
"This document will expire in %d days.":
|
||||
["Questo documento scadrà tra un giorno.", "Questo documento scadrà in %d giorni."],
|
||||
"This document will expire in %d months.":
|
||||
["Questo documento scadrà tra un mese.", "Questo documento scadrà in %d mesi."],
|
||||
"Please enter the password for this paste:":
|
||||
"Inserisci la password per questo messaggio:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Non riesco a decifrari i dati (Chiave errata?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Non riesco a cancellare il messaggio, non è stato salvato in modalità Distruggi-dopo-lettora.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"FOR YOUR EYES ONLY. Non chiudere questa finestra, il messaggio non può essere visualizzato una seconda volta.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Non riesco a decifrari il commento (Chiave errata?)",
|
||||
"Reply":
|
||||
"Rispondi",
|
||||
"Anonymous":
|
||||
"Anonimo",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar Anonino (Vizhash dell'indirizzo IP)",
|
||||
"Add comment":
|
||||
"Aggiungi un commento",
|
||||
"Optional nickname...":
|
||||
"Nickname opzionale...",
|
||||
"Post comment":
|
||||
"Invia commento",
|
||||
"Sending comment...":
|
||||
"Commento in fase di invio...",
|
||||
"Comment posted.":
|
||||
"Commento inviato.",
|
||||
"Could not refresh display: %s":
|
||||
"Non riesco ad aggiornare il display: %s",
|
||||
"unknown status":
|
||||
"errore sconosciuto",
|
||||
"server error or not responding":
|
||||
"errore o mancata risposta dal server",
|
||||
"Could not post comment: %s":
|
||||
"Impossibile inviare il commento: %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Invio messaggio (Muovi il mouse in modo casuale, per generare maggior entropia)...",
|
||||
"Sending paste...":
|
||||
"Messaggio in fase di invio...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Il tuo messaggio è qui: <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">([CTRL | CMD]+[C] per copiare il link)</span>",
|
||||
"Delete data":
|
||||
"Cancella i dati",
|
||||
"Could not create paste: %s":
|
||||
"Non rieco a creare il messaggio: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Non riesco a decifrare il messaggio: manca la chiave di decifrazione nell'URL (La chiave è parte integrante dell'URL. Per caso hai usato un Redirector o un altro servizio che ha rimosso una parte dell'URL?)",
|
||||
"Format": "Formato",
|
||||
"Plain Text": "Solo Testo",
|
||||
"Source Code": "Codice Sorgente",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Scarica Allegato",
|
||||
"Cloned file attached.": "Copia del file allegata.",
|
||||
"Attach a file": "Allega un file",
|
||||
"Remove attachment": "Rimuovi allegato",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Il tuo browser non supporta l'invio di file cifrati. Utilizza un browser più recente.",
|
||||
"Invalid attachment.": "Allegato non valido.",
|
||||
"Options": "Opzioni",
|
||||
"Shorten URL": "Accorcia URL",
|
||||
"Editor": "Editor",
|
||||
"Preview": "Preview",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"%s necessita che PATH termini con \"%s\". Aggiorna la variabile PATH nel tuo index.php.",
|
||||
"Decrypt":
|
||||
"Decrypt",
|
||||
"Enter password":
|
||||
"Inserisci la password",
|
||||
"Loading…": "Loading…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a> (in English)."
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s er en minimalistisk, åpen kildekode, elektronisk tilgjengelig pastebin hvor serveren ikke har kunnskap om dataene som limes inn. Dataene krypteres/dekrypteres <i>i nettleseren</i> ved hjelp av 256 bits AES. Mer informasjon om prosjektet på <a href=\"https://privatebin.info/\">prosjektsiden</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Fordi uvitenhet er lykke",
|
||||
"en": "no",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Innlegget eksisterer ikke, er utløpt eller har blitt slettet.",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"Beklager, %s krever php 5.3.0 eller nyere for å kjøre.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s krever konfigurasjonsdel [%s] å være til stede i konfigurasjonsfilen .",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Vennligst vent %d sekunder mellom hvert innlegg.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Innlegg er begrenset til %s av kryptert data.",
|
||||
"Invalid data.":
|
||||
"Ugyldige data.",
|
||||
"You are unlucky. Try again.":
|
||||
"Du er uheldig. Prøv igjen.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Beklager, det oppstod en feil ved lagring kommentar.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Beklager, det oppstod en feil ved lagring innlegg.",
|
||||
"Invalid paste ID.":
|
||||
"Feil innlegg ID.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Innlegg er ikke av type slett-etter-lesing.",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Feil slettingsnøkkel. Innlegg ble ikke fjernet.",
|
||||
"Paste was properly deleted.":
|
||||
"Innlegget er slettet.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"Javascript kreves for at %s skal fungere<br />Beklager ulempene.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s krever en moderne nettleser for å fungere.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Fortsatt bruker av Internet Explorer? Gjør deg selv en tjeneste og bytt til en moderne nettleser:",
|
||||
"New":
|
||||
"Ny",
|
||||
"Send":
|
||||
"Send",
|
||||
"Clone":
|
||||
"Kopier",
|
||||
"Raw text":
|
||||
"Ren tekst",
|
||||
"Expires":
|
||||
"Utgår",
|
||||
"Burn after reading":
|
||||
"Slett etter lesing",
|
||||
"Open discussion":
|
||||
"Åpen diskusjon",
|
||||
"Password (recommended)":
|
||||
"Passord (anbefalt)",
|
||||
"Discussion":
|
||||
"Diskusjon",
|
||||
"Toggle navigation":
|
||||
"Veksle navigasjon",
|
||||
"%d seconds": ["%d sekund", "%d sekunder"],
|
||||
"%d minutes": ["%d minutt", "%d minutter"],
|
||||
"%d hours": ["%d time", "%d timer"],
|
||||
"%d days": ["%d dag", "%d dager"],
|
||||
"%d weeks": ["%d uke", "%d uker"],
|
||||
"%d months": ["%d måned", "%d måneder"],
|
||||
"%d years": ["%d år", "%d år"],
|
||||
"Never":
|
||||
"Aldri",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Merk: Dette er en test tjeneste: Data kan slettes når som helst. Kattunger vil dø hvis du misbruker denne tjenesten.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Dette dokumentet vil utløpe om %d sekund.", "Dette dokumentet vil utløpe om %d sekunder."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Dette dokumentet vil utløpe om %d minutt.", "Dette dokumentet vil utløpe om %d minutter."],
|
||||
"This document will expire in %d hours.":
|
||||
["Dette dokumentet vil utløpe om %d time.", "Dette dokumentet vil utløpe om %d timer."],
|
||||
"This document will expire in %d days.":
|
||||
["Dette dokumentet vil utløpe om %d dag.", "Dette dokumentet vil utløpe om %d dager."],
|
||||
"This document will expire in %d months.":
|
||||
["Dette dokumentet vil utløpe om %d måned.", "Dette dokumentet vil utløpe om %d måneder."],
|
||||
"Please enter the password for this paste:":
|
||||
"Vennligst skriv inn passordet for dette innlegget:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Kunne ikke dekryptere data (Feil nøkkel?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Kan ikke slette innlegget, det ble ikke lagret i slett-etter-les modus.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"KUN FOR DINE ØYNE. Ikke lukk dette vinduet, denne meldingen kan ikke bli vist igjen.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Kan ikke dekryptere kommentar; Feil nøkkel?",
|
||||
"Reply":
|
||||
"Svar",
|
||||
"Anonymous":
|
||||
"Anonym",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Anonym avatar (Vizhash av IP adressen)",
|
||||
"Add comment":
|
||||
"Legg til kommentar",
|
||||
"Optional nickname...":
|
||||
"Valgfritt kallenavn...",
|
||||
"Post comment":
|
||||
"Send kommentar",
|
||||
"Sending comment...":
|
||||
"Sender Kommentar...",
|
||||
"Comment posted.":
|
||||
"Kommentar sendt.",
|
||||
"Could not refresh display: %s":
|
||||
"Kunne ikke oppdatere skjermen: %s",
|
||||
"unknown status":
|
||||
"ukjent status",
|
||||
"server error or not responding":
|
||||
"server feilet eller svarer ikke",
|
||||
"Could not post comment: %s":
|
||||
"Kunne ikke sende kommentar: %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Sender innlegg (Flytt musen for mere entropi)...",
|
||||
"Sending paste...":
|
||||
"Sender innlegg...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Ditt innlegg er <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Trykk [Ctrl]+[c] for å kopiere)</span>",
|
||||
"Delete data":
|
||||
"Slett data",
|
||||
"Could not create paste: %s":
|
||||
"Kunne ikke opprette innlegg: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Kan ikke dekryptere innlegg: Dekrypteringsnøkkelen mangler i adressen (Har du bruket en redirector eller en URL forkorter som fjerner en del av addressen?)",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Ren Tekst",
|
||||
"Source Code": "Kildekode",
|
||||
"Markdown": "Oppmerket",
|
||||
"Download attachment": "Last ned vedlegg",
|
||||
"Cloned file attached.": "Kopier vedlegg.",
|
||||
"Attach a file": "Legg til fil",
|
||||
"Remove attachment": "Slett vedlegg",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Nettleseren din støtter ikke å laste opp krypterte filer. Vennligst bruk en nyere nettleser.",
|
||||
"Invalid attachment.": "Ugyldig vedlegg.",
|
||||
"Options": "Alternativer",
|
||||
"Shorten URL": "Adresse-forkorter",
|
||||
"Editor": "Rediger",
|
||||
"Preview": "Forhåndsvis",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"%s krever at PATH ender på \"%s\". Vennligst oppdater PATH i index.php.",
|
||||
"Decrypt":
|
||||
"Dekrypter",
|
||||
"Enter password":
|
||||
"Skriv inn passord",
|
||||
"Loading…": "Laster…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Hvis denne meldingen ikke forsvinner kan du ta en titt på siden med <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">ofte stilte spørsmål</a> for informasjon om feilsøking."
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s es un 'pastebin' (o gestionari d'extrachs de tèxte e còdi font) minimalista e open source, dins lo qual lo servidor a pas cap de coneissença de las donadas mandadas. Las donadas son chifradas/deschifradas <i>dins lo navigator</i> per un chiframent AES 256 bits. Mai informacions sus <a href=\"https://privatebin.info/\">la pagina del projècte</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Perque l'ignorància es bonaür",
|
||||
"en": "oc",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Lo tèxte existís pas, a expirat, o es estat suprimit.",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"O planhèm, %s necessita php 5.3.0 o superior per foncionar.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s fa besonh de la seccion de configuracion [%s] dins lo fichièr de configuracion per foncionar.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Mercés d'esperar %d segondas entre cada publicacion.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Lo tèxte es limitat a %s de donadas chifradas.",
|
||||
"Invalid data.":
|
||||
"Donadas invalidas.",
|
||||
"You are unlucky. Try again.":
|
||||
"Pas cap de fortuna. Tornatz ensajar.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Error al moment de salvagardar lo comentari. O planhèm.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Error al moment de salvagardar lo tèxte. O planhèm.",
|
||||
"Invalid paste ID.":
|
||||
"ID del tèxte invalid.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Lo tèxte es pas del tip \"Escafar aprèp lectura\".",
|
||||
"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.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"JavaScript es requesit per far foncionar %s. <br />O planhèm per l'inconvenient.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s necessita un navigator modèrn per foncionar.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Encora sus Internet Explorer ? Fasètz-vos una favor, passatz a un navigator modèrn :",
|
||||
"New":
|
||||
"Nòu",
|
||||
"Send":
|
||||
"Mandar",
|
||||
"Clone":
|
||||
"Clonar",
|
||||
"Raw text":
|
||||
"Tèxte brut",
|
||||
"Expires":
|
||||
"Expira",
|
||||
"Burn after reading":
|
||||
"Escafar aprèp lectura",
|
||||
"Open discussion":
|
||||
"Autorizar la discussion",
|
||||
"Password (recommended)":
|
||||
"Senhal (recomandat)",
|
||||
"Discussion":
|
||||
"Discussion",
|
||||
"Toggle navigation":
|
||||
"Virar la navigacion",
|
||||
"%d seconds": ["%d segonda", "%d segondas"],
|
||||
"%d minutes": ["%d minuta", "%d minutas"],
|
||||
"%d hours": ["%d ora", "%d oras"],
|
||||
"%d days": ["%d jorn", "%d jorns"],
|
||||
"%d weeks": ["%d setmana", "%d setmanas"],
|
||||
"%d months": ["%d mes", "%d meses"],
|
||||
"%d years": ["%d an", "%d ans"],
|
||||
"Never":
|
||||
"Jamai",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Nota : Aquò es un servici d'espròva : las donadas pòdon èsser suprimidas a cada moment. De catons moriràn s'abusatz d'aqueste servici.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Ce document expirera dans %d seconde.", "Aqueste document expirarà dins %d segondas."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Ce document expirera dans %d minute.", "Aqueste document expirarà dins %d minutas."],
|
||||
"This document will expire in %d hours.":
|
||||
["Ce document expirera dans %d heure.", "Aqueste document expirarà dins %d oras."],
|
||||
"This document will expire in %d days.":
|
||||
["Ce document expirera dans %d jour.", "Aqueste document expirarà dins %d jorns."],
|
||||
"This document will expire in %d months.":
|
||||
["Ce document expirera dans %d mois.", "Aqueste document expirarà dins %d meses."],
|
||||
"Please enter the password for this paste:":
|
||||
"Picatz lo senhal per aqueste tèxte :",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Impossible de deschifrar las donadas (marrida clau ?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Impossible de suprimir lo tèxte, perque es pas estat gardat en mòde \"Escafar aprèp lectura\".",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"PER VÒSTRES UÈLHS SOLAMENT. Tampetz pas aquesta fenèstra, aqueste tèxte poirà pas mai èsser afichat.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Impossible de deschifrar lo comentari ; marrida clau ?",
|
||||
"Reply":
|
||||
"Respondre",
|
||||
"Anonymous":
|
||||
"Anonime",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar anonime (Vizhash de l'adreça IP)",
|
||||
"Add comment":
|
||||
"Apondre un comentari",
|
||||
"Optional nickname...":
|
||||
"Escais opcional...",
|
||||
"Post comment":
|
||||
"Mandar lo comentari",
|
||||
"Sending comment...":
|
||||
"Mandadís del comentari...",
|
||||
"Comment posted.":
|
||||
"Comentari mandat.",
|
||||
"Could not refresh display: %s":
|
||||
"Impossible d'actualizar l'afichatge : %s",
|
||||
"unknown status":
|
||||
"Estatut desconegut",
|
||||
"server error or not responding":
|
||||
"Lo servidor respond pas o a rencontrat una error",
|
||||
"Could not post comment: %s":
|
||||
"Impossible de mandar lo comentari : %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Mandadís del tèxte (Mercés de bolegar vòstra mirga per mai entropia)...",
|
||||
"Sending paste...":
|
||||
"Mandadís del tèxte...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Vòstre tèxte es disponible a l'adreça <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Picatz sus [Ctrl]+[c] per copiar)</span>",
|
||||
"Delete data":
|
||||
"Supprimir las donadas del tèxte",
|
||||
"Could not create paste: %s":
|
||||
"Impossible de crear lo tèxte : %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Impossible de deschifrar lo tèxte : Clau de deschiframent absenta de l'URL (Avètz utilizat un redirector o un site de reduccion d'URL que suprimís una partida de l'URL ?)",
|
||||
"B": "o",
|
||||
"KiB": "Kio",
|
||||
"MiB": "Mio",
|
||||
"GiB": "Gio",
|
||||
"TiB": "Tio",
|
||||
"PiB": "Pio",
|
||||
"EiB": "Eio",
|
||||
"ZiB": "Zio",
|
||||
"YiB": "Yio",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Tèxte brut",
|
||||
"Source Code": "Còdi font",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Telecargar la pèça junta",
|
||||
"Cloned file attached.": "Clonar lo fichièr junt.",
|
||||
"Attach a file": "Juntar un fichièr ",
|
||||
"Remove attachment": "Levar la pèca junta",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Vòstre navigator es pas compatible amb lo mandadís de fichièrs chifrats. Mercés d'emplegar un navigator mai recent.",
|
||||
"Invalid attachment.": "Pèça junta invalida.",
|
||||
"Options": "Opcions",
|
||||
"Shorten URL": "Acorchir l'URL",
|
||||
"Editor": "Editar",
|
||||
"Preview": "Previsualizar",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"%s demanda que lo PATH termine en \"%s\". Mercés de metre a jorn lo PATH dins vòstre index.php.",
|
||||
"Decrypt":
|
||||
"Deschifrar",
|
||||
"Enter password":
|
||||
"Picatz lo senhal",
|
||||
"Loading…": "Cargament…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"Se per cas aqueste messatge quita pas de s'afichar mercés de gaitar <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">aquesta FAQ per las solucions</a> (en Anglés)."
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s jest minimalistycznym, otwartoźródłowym serwisem typu pastebin, w którym serwer nie ma jakichkolwiek informacji o tym, co jest wklejane. Dane są szyfrowane i deszyfrowane <i>w przeglądarce</i> z użyciem 256-bitowego klucza AES. Więcej informacji na <a href=\"https://privatebin.info/\">stronie projektu</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Ponieważ ignorancja jest cnotą",
|
||||
"en": "pl",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Wklejka nie istnieje, wygasła albo została usunięta.",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"%s wymaga PHP w wersji 5.3.0 lub nowszej, sorry.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s wymaga obecności sekcji [%s] w pliku konfiguracyjnym.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Poczekaj %d sekund pomiędzy każdą wklejką.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Wklejka jest limitowana do %s zaszyfrowanych danych.",
|
||||
"Invalid data.":
|
||||
"Nieprawidłowe dane.",
|
||||
"You are unlucky. Try again.":
|
||||
"Miałeś pecha. Spróbuj ponownie.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Błąd przy zapisywaniu komentarza, sorry.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Błąd przy zapisywaniu wklejki, sorry.",
|
||||
"Invalid paste ID.":
|
||||
"Nieprawidłowe ID wklejki.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Ta wklejka nie ulega autodestrukcji po przeczytaniu.",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Nieprawidłowy token usuwania. Wklejka nie została usunięta.",
|
||||
"Paste was properly deleted.":
|
||||
"Wklejka usunięta poprawnie.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"Do działania %sa jest wymagany JavaScript. Przepraszamy za tę niedogodność.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s wymaga do działania nowoczesnej przeglądarki.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Cały czas używasz Internet Explorera? Zrób sobie przysługę, przesiądź się na nowoczesną przeglądarkę:",
|
||||
"New":
|
||||
"Nowa",
|
||||
"Send":
|
||||
"Wyślij",
|
||||
"Clone":
|
||||
"Sklonuj",
|
||||
"Raw text":
|
||||
"Czysty tekst",
|
||||
"Expires":
|
||||
"Wygasa za",
|
||||
"Burn after reading":
|
||||
"Zniszcz po przeczytaniu",
|
||||
"Open discussion":
|
||||
"Otwarta dyskusja",
|
||||
"Password (recommended)":
|
||||
"Hasło (zalecane)",
|
||||
"Discussion":
|
||||
"Dyskusja",
|
||||
"Toggle navigation":
|
||||
"Przełącz nawigację",
|
||||
"%d seconds": ["%d second", "%d second", "%d second"],
|
||||
"%d minutes": ["%d minut", "%d minut", "%d minut"],
|
||||
"%d hours": ["%d godzina", "%d godzina", "%d godzinę"],
|
||||
"%d days": ["%d dzień", "%d dzień", "%d dzień"],
|
||||
"%d weeks": ["%d tydzień", "%d tydzień", "%d tydzień"],
|
||||
"%d months": ["%d miesiąc", "%d miesiąc", "%d miesiąc"],
|
||||
"%d years": ["%d rok", "%d rok", "%d rok"],
|
||||
"Never":
|
||||
"nigdy",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Notka: To jest usługa testowa. Dane mogą zostać usunięte w dowolnym momencie. Kociątka umrą, jeśli nadużyjesz tej usługi.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Ten dokument wygaśnie za %d sekundę.", "Ten dokument wygaśnie za %d sekund."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Ten dokument wygaśnie za %d minutę.", "Ten dokument wygaśnie za %d minut."],
|
||||
"This document will expire in %d hours.":
|
||||
["Ten dokument wygaśnie za godzinę.", "Ten dokument wygaśnie za %d godzin."],
|
||||
"This document will expire in %d days.":
|
||||
["Ten dokument wygaśnie za %d dzień.", "Ten dokument wygaśnie za %d dni."],
|
||||
"This document will expire in %d months.":
|
||||
["Ten dokument wygaśnie za miesiąc.", "Ten dokument wygaśnie za %d miesięcy."],
|
||||
"Please enter the password for this paste:":
|
||||
"Wpisz hasło dla tej wklejki:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Nie udało się odszyfrować danych (zły klucz?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Nie udało się usunąć wklejki, nie została zapisana w trybie zniszczenia po przeczytaniu.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"TYLKO DO TWOJEGO WGLĄDU. Nie zamykaj tego okna, ta wiadomość nie będzie mogła być wyświetlona ponownie.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Nie udało się odszyfrować komentarza; zły klucz?",
|
||||
"Reply":
|
||||
"Odpowiedz",
|
||||
"Anonymous":
|
||||
"Anonim",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Anonimowy avatar (Vizhash z adresu IP)",
|
||||
"Add comment":
|
||||
"Dodaj komentarz",
|
||||
"Optional nickname...":
|
||||
"Opcjonalny nick...",
|
||||
"Post comment":
|
||||
"Wyślij komentarz",
|
||||
"Sending comment...":
|
||||
"Wysyłanie komentarza...",
|
||||
"Comment posted.":
|
||||
"Wysłano komentarz.",
|
||||
"Could not refresh display: %s":
|
||||
"Nie można odświeżyć widoku: %s",
|
||||
"unknown status":
|
||||
"nieznany status",
|
||||
"server error or not responding":
|
||||
"bląd serwera lub brak odpowiedzi",
|
||||
"Could not post comment: %s":
|
||||
"Nie udało się wysłać komentarza: %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Wysyłanie wklejki (proszę poruszać myszą aby uzyskać większą entropię)...",
|
||||
"Sending paste...":
|
||||
"Wysyłanie wklejki...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Twoja wklejka to <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(wciśnij [Ctrl]+[c] aby skopiować)</span>",
|
||||
"Delete data":
|
||||
"Skasuj dane",
|
||||
"Could not create paste: %s":
|
||||
"Nie udało się utworzyć wklejki: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Nie udało się odszyfrować wklejki - brak klucza deszyfrującego w adresie (użyłeś skracacza linków, który ucina część adresu?)",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Czysty tekst",
|
||||
"Source Code": "Kod źródłowy",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Pobierz załącznik",
|
||||
"Cloned file attached.": "Sklonowano załączony plik.",
|
||||
"Attach a file": "Załącz plik",
|
||||
"Remove attachment": "Usuń załącznik",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Twoja przeglądarka nie wspiera wysyłania zaszyfrowanych plików. Użyj nowszej przeglądarki.",
|
||||
"Invalid attachment.": "Nieprawidłowy załącznik.",
|
||||
"Options": "Opcje",
|
||||
"Shorten URL": "Skróć adres URL",
|
||||
"Editor": "Edytować",
|
||||
"Preview": "Zapowiedź",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
|
||||
"Decrypt":
|
||||
"Decrypt",
|
||||
"Enter password":
|
||||
"Wpisz hasło",
|
||||
"Loading…": "Loading…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a> (in English)."
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
{
|
||||
"PrivateBin": "PrivateBin",
|
||||
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
|
||||
"%s je minimalističen, odprtokodni spletni 'pastebin', kjer server ne ve ničesar o prilepljenih podatkih. Podatki so zakodirani/odkodirani <i>v brskalniku</i> z uporabo 256 bitnega AES. Več informacij na < href=\"https://privatebin.info/\">spletni strani projekta.</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Ker kar ne veš ne boli.",
|
||||
"en": "sl",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Prilepek ne obstaja, mu je potekla življenjska doba, ali pa je izbrisan.",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"Oprosti, %s za delovanje potrebuje vsaj php 5.3.0.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s potrebuje sekcijo konfiguracij [%s] v konfiguracijski datoteki.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Prosim počakaj vsaj %d sekund pred vsako naslednjo objavo.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Velikost prilepka je omejena na %s zakodiranih podatkov.",
|
||||
"Invalid data.":
|
||||
"Neveljavni podatki.",
|
||||
"You are unlucky. Try again.":
|
||||
"Nimaš sreče, poskusi ponovno.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Nekaj je šlo narobe pri shranjevanju komentarja. Oprosti.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Nekaj je šlo narobe pri shranjevanju prilepka. Oprosti.",
|
||||
"Invalid paste ID.":
|
||||
"Napačen ID prilepka.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Prilepek ni tipa zažgi-po-branju.",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Napačen token za izbris. Prilepek ni bil izbrisan..",
|
||||
"Paste was properly deleted.":
|
||||
"Prilepek je uspešno izbrisan.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"Da %s deluje, moraš vklopiti JavaScript.<br />Oprosti za povročene nevšečnosti.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s za svoje delovanje potrebuje moderen brskalnik.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Še vedno uporabljaš Internet Explorer? Naredi si uslugo, preklopi na moderen brskalnik:",
|
||||
"New":
|
||||
"Nov prilepek",
|
||||
"Send":
|
||||
"Pošlji",
|
||||
"Clone":
|
||||
"Kloniraj",
|
||||
"Raw text":
|
||||
"Surov tekst",
|
||||
"Expires":
|
||||
"Poteče",
|
||||
"Burn after reading":
|
||||
"Zažgi (pobriši) po branju",
|
||||
"Open discussion":
|
||||
"Dovoli razpravo",
|
||||
"Password (recommended)":
|
||||
"Geslo (priporočeno)",
|
||||
"Discussion":
|
||||
"Razprava",
|
||||
"Toggle navigation":
|
||||
"Preklopi navigacijo",
|
||||
"%d seconds": ["%d sekunda", "%d sekundi", "%d sekunde", "%d sekund"],
|
||||
"%d minutes": ["%d minuta", "%d minuti", "%d minute", "%d minut"],
|
||||
"%d hours": ["%d ura", "%d uri", "%d ure", "%d ur"],
|
||||
"%d days": ["%d dan", "%d dneva", "%d dnevi", "%d dni"],
|
||||
"%d weeks": ["%d teden", "%d tedna", "%d tedni", "%d tednov"],
|
||||
"%d months": ["%d mesec", "%d meseca", "%d meseci", "%d mesecev"],
|
||||
"%d years": ["%d leto", "%d leti", "%d leta", "%d let"],
|
||||
"Never":
|
||||
"Nikoli",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Ne pozabi: To je testna storitev: Podatki so lahko kadarkoli pobrisani. Mucki bodo umrli, če boš zlorabljala to storitev.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Ta dokument bo potekel čez %d sekundo.", "Ta dokument bo potekel čez %d sekundi.", "Ta dokument bo potekel čez %d sekunde.", "Ta dokument bo potekel čez %d sekund."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Ta dokument bo potekel čez %d minuto.", "Ta dokument bo potekel čez %d minuti.", "Ta dokument bo potekel čez %d minute.", "Ta dokument bo potekel čez %d minut."],
|
||||
"This document will expire in %d hours.":
|
||||
["Ta dokument bo potekel čez %d uro.", "Ta dokument bo potekel čez %d uri.", "Ta dokument bo potekel čez %d ure.", "Ta dokument bo potekel čez %d ur."],
|
||||
"This document will expire in %d days.":
|
||||
["Ta dokument bo potekel čez %d dan.", "Ta dokument bo potekel čez %d dni.", "Ta dokument bo potekel čez %d dni.", "Ta dokument bo potekel čez %d dni."],
|
||||
"This document will expire in %d months.":
|
||||
["Ta dokument bo potekel čez %d mesec.", "Ta dokument bo potekel čez %d meseca.", "Ta dokument bo potekel čez %d mesece.", "Ta dokument bo potekel čez %d mesecev."],
|
||||
"Please enter the password for this paste:":
|
||||
"Prosim vnesi geslo tega prilepka:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Nemogoče odkodirati podakte (Imaš napačen ključ?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Prilepek je nemogoče izbrisati, ni bil shranjen v načinu \"zažgi po branju\".",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"SAMO ZA TVOJE OČI. Ne zapri tega okna (zavihka), to sporočilo ne bo prikazano nikoli več.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Ne morem odkodirati komentarja: Imaš napačen ključ?",
|
||||
"Reply":
|
||||
"Odgovori",
|
||||
"Anonymous":
|
||||
"Aninomno",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Anonimen avatar (Vizhash IP naslova)",
|
||||
"Add comment":
|
||||
"Dodaj komentar",
|
||||
"Optional nickname...":
|
||||
"Uporabniško ime (lahko izpustiš)",
|
||||
"Post comment":
|
||||
"Objavi komentar",
|
||||
"Sending comment...":
|
||||
"Pošiljam komentar ...",
|
||||
"Comment posted.":
|
||||
"Komentar poslan.",
|
||||
"Could not refresh display: %s":
|
||||
"Ne morem osvežiti zaslona : %s",
|
||||
"unknown status":
|
||||
"neznan status",
|
||||
"server error or not responding":
|
||||
"napaka na strežniku, ali pa se strežnik ne odziva",
|
||||
"Could not post comment: %s":
|
||||
"Komentarja ni bilo mogoče objaviti : %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Pošiljam prilepek (prosim premakni svojo miško za več entropije) ...",
|
||||
"Sending paste...":
|
||||
"Pošiljam prilepek...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Tvoj prilepek je dostopen na naslovu: <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Pritisni [Ctrl]+[c] ali [Cmd] + [c] in skopiraj)</span>",
|
||||
"Delete data":
|
||||
"Izbriši podatke",
|
||||
"Could not create paste: %s":
|
||||
"Ne morem ustvariti prilepka: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Ne morem odkodirati prilepka: V URL-ju manjka ključ (A si uporabil krajšalnik URL-jev, ki odstrani del URL-ja?)",
|
||||
"B": "o",
|
||||
"KiB": "KB",
|
||||
"MiB": "MB",
|
||||
"GiB": "GB",
|
||||
"TiB": "TB",
|
||||
"PiB": "PB",
|
||||
"EiB": "EB",
|
||||
"ZiB": "ZB",
|
||||
"YiB": "YB",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Surov tekst",
|
||||
"Source Code": "Odprta koda",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Pretoči priponko",
|
||||
"Cloned file attached.": "Pripeta datoteka klonirana",
|
||||
"Attach a file": "Pripni datoteko",
|
||||
"Remove attachment": "Odstrani priponko",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Tvoj brskalnik ne omogoča nalaganje zakodiranih datotek. Prosim uporabi novejši brskalnik.",
|
||||
"Invalid attachment.": "Neveljavna priponka.",
|
||||
"Options": "Možnosti",
|
||||
"Shorten URL": "Skrajšajte URL",
|
||||
"Editor": "Uredi",
|
||||
"Preview": "Predogled",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
|
||||
"Decrypt":
|
||||
"Decrypt",
|
||||
"Enter password":
|
||||
"Prosim vnesi geslo",
|
||||
"Loading…": "Loading…",
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
|
||||
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a> (in English)."
|
||||
}
|
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 671 B |
Before Width: | Height: | Size: 469 B |
Before Width: | Height: | Size: 749 B |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 943 B |
Before Width: | Height: | Size: 266 B |
Before Width: | Height: | Size: 157 B |
Before Width: | Height: | Size: 183 B |
Before Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 196 B |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.9 KiB |
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* 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
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
// change this, if your php files and data is outside of your webservers document root
|
||||
define('PATH', '');
|
||||
|
||||
define('PUBLIC_PATH', __DIR__);
|
||||
require PATH . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||
new PrivateBin\PrivateBin;
|
@ -1,7 +0,0 @@
|
||||
---
|
||||
instrumentation:
|
||||
excludes:
|
||||
- jquery-3.1.1.js
|
||||
baseline-file: ../tst/log/js-coverage-baseline.json
|
||||
reporting:
|
||||
dir: ../tst/log/js-coverage-report
|
@ -1,237 +0,0 @@
|
||||
/*
|
||||
* $Id: base64.js,v 1.7 2012/08/23 10:30:18 dankogai Exp dankogai $
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
* https://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* References:
|
||||
* https://en.wikipedia.org/wiki/Base64
|
||||
*/
|
||||
|
||||
(function(global){
|
||||
|
||||
var b64chars
|
||||
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
|
||||
var b64charcodes = function(){
|
||||
var a = [];
|
||||
var codeA = 'A'.charCodeAt(0);
|
||||
var codea = 'a'.charCodeAt(0);
|
||||
var code0 = '0'.charCodeAt(0);
|
||||
for (var i = 0; i < 26; i ++) a.push(codeA + i);
|
||||
for (var i = 0; i < 26; i ++) a.push(codea + i);
|
||||
for (var i = 0; i < 10; i ++) a.push(code0 + i);
|
||||
a.push('+'.charCodeAt(0));
|
||||
a.push('/'.charCodeAt(0));
|
||||
return a;
|
||||
}();
|
||||
|
||||
var b64tab = function(bin){
|
||||
var t = {};
|
||||
for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
|
||||
return t;
|
||||
}(b64chars);
|
||||
|
||||
var stringToArray = function(s){
|
||||
var a = [];
|
||||
for (var i = 0, l = s.length; i < l; i ++) a[i] = s.charCodeAt(i);
|
||||
return a;
|
||||
};
|
||||
|
||||
var convertUTF8ArrayToBase64 = function(bin){
|
||||
var padlen = 0;
|
||||
while (bin.length % 3){
|
||||
bin.push(0);
|
||||
padlen++;
|
||||
};
|
||||
var b64 = [];
|
||||
for (var i = 0, l = bin.length; i < l; i += 3){
|
||||
var c0 = bin[i], c1 = bin[i+1], c2 = bin[i+2];
|
||||
if (c0 >= 256 || c1 >= 256 || c2 >= 256)
|
||||
throw 'unsupported character found';
|
||||
var n = (c0 << 16) | (c1 << 8) | c2;
|
||||
b64.push(
|
||||
b64charcodes[ n >>> 18],
|
||||
b64charcodes[(n >>> 12) & 63],
|
||||
b64charcodes[(n >>> 6) & 63],
|
||||
b64charcodes[ n & 63]
|
||||
);
|
||||
}
|
||||
while (padlen--) b64[b64.length - padlen - 1] = '='.charCodeAt(0);
|
||||
return chunkStringFromCharCodeApply(b64);
|
||||
};
|
||||
|
||||
var convertBase64ToUTF8Array = function(b64){
|
||||
b64 = b64.replace(/[^A-Za-z0-9+\/]+/g, '');
|
||||
var bin = [];
|
||||
var padlen = b64.length % 4;
|
||||
for (var i = 0, l = b64.length; i < l; i += 4){
|
||||
var n = ((b64tab[b64.charAt(i )] || 0) << 18)
|
||||
| ((b64tab[b64.charAt(i+1)] || 0) << 12)
|
||||
| ((b64tab[b64.charAt(i+2)] || 0) << 6)
|
||||
| ((b64tab[b64.charAt(i+3)] || 0));
|
||||
bin.push(
|
||||
( n >> 16 ),
|
||||
( (n >> 8) & 0xff ),
|
||||
( n & 0xff )
|
||||
);
|
||||
}
|
||||
bin.length -= [0,0,2,1][padlen];
|
||||
return bin;
|
||||
};
|
||||
|
||||
var convertUTF16ArrayToUTF8Array = function(uni){
|
||||
var bin = [];
|
||||
for (var i = 0, l = uni.length; i < l; i++){
|
||||
var n = uni[i];
|
||||
if (n < 0x80)
|
||||
bin.push(n);
|
||||
else if (n < 0x800)
|
||||
bin.push(
|
||||
0xc0 | (n >>> 6),
|
||||
0x80 | (n & 0x3f));
|
||||
else
|
||||
bin.push(
|
||||
0xe0 | ((n >>> 12) & 0x0f),
|
||||
0x80 | ((n >>> 6) & 0x3f),
|
||||
0x80 | (n & 0x3f));
|
||||
}
|
||||
return bin;
|
||||
};
|
||||
|
||||
var convertUTF8ArrayToUTF16Array = function(bin){
|
||||
var uni = [];
|
||||
for (var i = 0, l = bin.length; i < l; i++){
|
||||
var c0 = bin[i];
|
||||
if (c0 < 0x80){
|
||||
uni.push(c0);
|
||||
}else{
|
||||
var c1 = bin[++i];
|
||||
if (c0 < 0xe0){
|
||||
uni.push(((c0 & 0x1f) << 6) | (c1 & 0x3f));
|
||||
}else{
|
||||
var c2 = bin[++i];
|
||||
uni.push(
|
||||
((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) | (c2 & 0x3f)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return uni;
|
||||
};
|
||||
|
||||
var convertUTF8StringToBase64 = function(bin){
|
||||
return convertUTF8ArrayToBase64(stringToArray(bin));
|
||||
};
|
||||
|
||||
var convertBase64ToUTF8String = function(b64){
|
||||
return chunkStringFromCharCodeApply(convertBase64ToUTF8Array(b64));
|
||||
};
|
||||
|
||||
var convertUTF8StringToUTF16Array = function(bin){
|
||||
return convertUTF8ArrayToUTF16Array(stringToArray(bin));
|
||||
};
|
||||
|
||||
var convertUTF8ArrayToUTF16String = function(bin){
|
||||
return chunkStringFromCharCodeApply(convertUTF8ArrayToUTF16Array(bin));
|
||||
};
|
||||
|
||||
var convertUTF8StringToUTF16String = function(bin){
|
||||
return chunkStringFromCharCodeApply(
|
||||
convertUTF8ArrayToUTF16Array(stringToArray(bin))
|
||||
);
|
||||
};
|
||||
|
||||
var convertUTF16StringToUTF8Array = function(uni){
|
||||
return convertUTF16ArrayToUTF8Array(stringToArray(uni));
|
||||
};
|
||||
|
||||
var convertUTF16ArrayToUTF8String = function(uni){
|
||||
return chunkStringFromCharCodeApply(convertUTF16ArrayToUTF8Array(uni));
|
||||
};
|
||||
|
||||
var convertUTF16StringToUTF8String = function(uni){
|
||||
return chunkStringFromCharCodeApply(
|
||||
convertUTF16ArrayToUTF8Array(stringToArray(uni))
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
* String.fromCharCode.apply will only handle arrays as big as 65536,
|
||||
* after that it'll return a truncated string with no warning.
|
||||
*/
|
||||
var chunkStringFromCharCodeApply = function(arr){
|
||||
var strs = [], i;
|
||||
for (i = 0; i < arr.length; i += 65536){
|
||||
strs.push(String.fromCharCode.apply(String, arr.slice(i, i+65536)));
|
||||
}
|
||||
return strs.join('');
|
||||
};
|
||||
|
||||
if (global.btoa){
|
||||
var btoa = global.btoa;
|
||||
var convertUTF16StringToBase64 = function (uni){
|
||||
return btoa(convertUTF16StringToUTF8String(uni));
|
||||
};
|
||||
}
|
||||
else {
|
||||
var btoa = convertUTF8StringToBase64;
|
||||
var convertUTF16StringToBase64 = function (uni){
|
||||
return convertUTF8ArrayToBase64(convertUTF16StringToUTF8Array(uni));
|
||||
};
|
||||
}
|
||||
|
||||
if (global.atob){
|
||||
var atob = global.atob;
|
||||
var convertBase64ToUTF16String = function (b64){
|
||||
return convertUTF8StringToUTF16String(atob(b64));
|
||||
};
|
||||
}
|
||||
else {
|
||||
var atob = convertBase64ToUTF8String;
|
||||
var convertBase64ToUTF16String = function (b64){
|
||||
return convertUTF8ArrayToUTF16String(convertBase64ToUTF8Array(b64));
|
||||
};
|
||||
}
|
||||
|
||||
global.Base64 = {
|
||||
convertUTF8ArrayToBase64:convertUTF8ArrayToBase64,
|
||||
convertByteArrayToBase64:convertUTF8ArrayToBase64,
|
||||
convertBase64ToUTF8Array:convertBase64ToUTF8Array,
|
||||
convertBase64ToByteArray:convertBase64ToUTF8Array,
|
||||
convertUTF16ArrayToUTF8Array:convertUTF16ArrayToUTF8Array,
|
||||
convertUTF16ArrayToByteArray:convertUTF16ArrayToUTF8Array,
|
||||
convertUTF8ArrayToUTF16Array:convertUTF8ArrayToUTF16Array,
|
||||
convertByteArrayToUTF16Array:convertUTF8ArrayToUTF16Array,
|
||||
convertUTF8StringToBase64:convertUTF8StringToBase64,
|
||||
convertBase64ToUTF8String:convertBase64ToUTF8String,
|
||||
convertUTF8StringToUTF16Array:convertUTF8StringToUTF16Array,
|
||||
convertUTF8ArrayToUTF16String:convertUTF8ArrayToUTF16String,
|
||||
convertByteArrayToUTF16String:convertUTF8ArrayToUTF16String,
|
||||
convertUTF8StringToUTF16String:convertUTF8StringToUTF16String,
|
||||
convertUTF16StringToUTF8Array:convertUTF16StringToUTF8Array,
|
||||
convertUTF16StringToByteArray:convertUTF16StringToUTF8Array,
|
||||
convertUTF16ArrayToUTF8String:convertUTF16ArrayToUTF8String,
|
||||
convertUTF16StringToUTF8String:convertUTF16StringToUTF8String,
|
||||
convertUTF16StringToBase64:convertUTF16StringToBase64,
|
||||
convertBase64ToUTF16String:convertBase64ToUTF16String,
|
||||
fromBase64:convertBase64ToUTF8String,
|
||||
toBase64:convertUTF8StringToBase64,
|
||||
atob:atob,
|
||||
btoa:btoa,
|
||||
utob:convertUTF16StringToUTF8String,
|
||||
btou:convertUTF8StringToUTF16String,
|
||||
encode:convertUTF16StringToBase64,
|
||||
encodeURI:function(u){
|
||||
return convertUTF16StringToBase64(u).replace(/[+\/]/g, function(m0){
|
||||
return m0 == '+' ? '-' : '_';
|
||||
}).replace(/=+$/, '');
|
||||
},
|
||||
decode:function(a){
|
||||
return convertBase64ToUTF16String(a.replace(/[-_]/g, function(m0){
|
||||
return m0 == '-' ? '+' : '/';
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
})(this);
|
@ -1,16 +0,0 @@
|
||||
{
|
||||
"@context": {
|
||||
"so": "https://schema.org/",
|
||||
"status": "so:Integer",
|
||||
"id": "so:name",
|
||||
"parentid": "so:name",
|
||||
"url: {
|
||||
"@id": "so:url",
|
||||
"@type": "@id"
|
||||
},
|
||||
"data": "so:Text",
|
||||
"meta": {
|
||||
"@id": "?jsonld=commentmeta"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"@context": {
|
||||
"so": "https://schema.org/",
|
||||
"postdate": "so:Integer",
|
||||
"nickname": "so:Text",
|
||||
"vizhash": "so:Text"
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
{
|
||||
"@context": {
|
||||
"so": "https://schema.org/",
|
||||
"status": {"@id": "so:Integer"},
|
||||
"id": {"@id": "so:name"},
|
||||
"deletetoken": {"@id": "so:Text"},
|
||||
"url": {
|
||||
"@type": "@id",
|
||||
"@id": "so:url"
|
||||
},
|
||||
"data": {"@id": "so:Text"},
|
||||
"attachment": {"@id": "so:Text"},
|
||||
"attachmentname": {"@id": "so:Text"},
|
||||
"meta": {
|
||||
"@id": "?jsonld=pastemeta"
|
||||
},
|
||||
"comments": {
|
||||
"@id": "?jsonld=comment",
|
||||
"@container": "@list"
|
||||
},
|
||||
"comment_count": {"@id": "so:Integer"},
|
||||
"comment_offset": {"@id": "so:Integer"}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"@context": {
|
||||
"so": "https://schema.org/",
|
||||
"formatter": {"@id": "so:Text"},
|
||||
"postdate": {"@id": "so:Integer"},
|
||||
"opendiscussion": {"@id": "so:True"},
|
||||
"burnafterreading": {"@id": "so:True"},
|
||||
"expire_date": {"@id": "so:Integer"},
|
||||
"remaining_time": {"@id": "so:Integer"}
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
|
||||
(function(){function R(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a=
|
||||
b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a<f;++a){var h=b[a];if(/\\[bdsw]/i.test(h))c.push(h);else{var h=d(h),l;a+2<f&&"-"===b[a+1]?(l=d(b[a+2]),a+=2):l=h;e.push([h,l]);l<65||h>122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=f[1]+1?f[1]=Math.max(f[1],h[1]):b.push(f=h);for(a=0;a<b.length;++a)h=b[a],c.push(g(h[0])),
|
||||
h[1]>h[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f<c;++f){var l=a[f];l==="("?++h:"\\"===l.charAt(0)&&(l=+l.substring(1))&&(l<=h?d[l]=-1:a[f]=g(l))}for(f=1;f<d.length;++f)-1===d[f]&&(d[f]=++x);for(h=f=0;f<c;++f)l=a[f],l==="("?(++h,d[h]||(a[f]="(?:")):"\\"===l.charAt(0)&&(l=+l.substring(1))&&l<=h&&
|
||||
(a[f]="\\"+d[l]);for(f=0;f<c;++f)"^"===a[f]&&"^"!==a[f+1]&&(a[f]="");if(e.ignoreCase&&m)for(f=0;f<c;++f)l=a[f],e=l.charAt(0),l.length>=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k<c;++k){var i=a[k];if(i.ignoreCase)j=!0;else if(/[a-z]/i.test(i.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){m=!0;j=!1;break}}for(var r={b:8,t:9,n:10,v:11,
|
||||
f:12,r:13},n=[],k=0,c=a.length;k<c;++k){i=a[k];if(i.global||i.multiline)throw Error(""+i);n.push("(?:"+s(i)+")")}return RegExp(n.join("|"),j?"gi":"g")}function S(a,d){function g(a){var c=a.nodeType;if(c==1){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)g(c);c=a.nodeName.toLowerCase();if("br"===c||"li"===c)s[j]="\n",m[j<<1]=x++,m[j++<<1|1]=a}}else if(c==3||c==4)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[\t\n\r ]+/g," "),s[j]=c,m[j<<1]=x,x+=c.length,m[j++<<1|1]=
|
||||
a)}var b=/(?:^|\s)nocode(?:\s|$)/,s=[],x=0,m=[],j=0;g(a);return{a:s.join("").replace(/\n$/,""),d:m}}function H(a,d,g,b){d&&(a={a:d,e:a},g(a),b.push.apply(b,a.g))}function T(a){for(var d=void 0,g=a.firstChild;g;g=g.nextSibling)var b=g.nodeType,d=b===1?d?a:g:b===3?U.test(g.nodeValue)?a:d:d;return d===a?void 0:d}function D(a,d){function g(a){for(var j=a.e,k=[j,"pln"],c=0,i=a.a.match(s)||[],r={},n=0,e=i.length;n<e;++n){var z=i[n],w=r[z],t=void 0,f;if(typeof w==="string")f=!1;else{var h=b[z.charAt(0)];
|
||||
if(h)t=z.match(h[1]),w=h[0];else{for(f=0;f<x;++f)if(h=d[f],t=z.match(h[1])){w=h[0];break}t||(w="pln")}if((f=w.length>=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c<i;++c){var r=
|
||||
g[c],n=r[3];if(n)for(var e=n.length;--e>=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=R(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
|
||||
q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com",
|
||||
/^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+
|
||||
s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,
|
||||
q],["pun",RegExp(b),q]);return D(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=
|
||||
c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i<c.length;++i)b(c[i]);d===(d|0)&&c[0].setAttribute("value",d);var r=j.createElement("ol");
|
||||
r.className="linenums";for(var d=Math.max(0,d-1|0)||0,i=0,n=c.length;i<n;++i)k=c[i],k.className="L"+(i+d)%10,k.firstChild||k.appendChild(j.createTextNode("\u00a0")),r.appendChild(k);a.appendChild(r)}function p(a,d){for(var g=d.length;--g>=0;){var b=d[g];F.hasOwnProperty(b)?E.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*</.test(d)?"default-markup":"default-code";return F[a]}function K(a){var d=a.h;try{var g=S(a.c,a.i),b=g.a;
|
||||
a.a=b;a.d=g.d;a.e=0;I(d,b)(a);var s=/\bMSIE\s(\d+)/.exec(navigator.userAgent),s=s&&+s[1]<=8,d=/\n/g,x=a.a,m=x.length,g=0,j=a.d,k=j.length,b=0,c=a.g,i=c.length,r=0;c[i]=m;var n,e;for(e=n=0;e<i;)c[e]!==c[e+2]?(c[n++]=c[e++],c[n++]=c[e++]):e+=2;i=n;for(e=n=0;e<i;){for(var p=c[e],w=c[e+1],t=e+2;t+2<=i&&c[t+1]===w;)t+=2;c[n++]=p;c[n++]=w;e=t}c.length=n;var f=a.c,h;if(f)h=f.style.display,f.style.display="none";try{for(;b<k;){var l=j[b+2]||m,B=c[r+2]||m,t=Math.min(l,B),A=j[b+1],G;if(A.nodeType!==1&&(G=x.substring(g,
|
||||
t))){s&&(G=G.replace(d,"\r"));A.nodeValue=G;var L=A.ownerDocument,o=L.createElement("span");o.className=c[r+1];var v=A.parentNode;v.replaceChild(o,A);o.appendChild(A);g<l&&(j[b+1]=A=L.createTextNode(x.substring(t,l)),v.insertBefore(A,o.nextSibling))}g=t;g>=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){E.console&&console.log(u&&u.stack||u)}}var E=window,y=["break,continue,do,else,for,if,return,while"],C=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
|
||||
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[C,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],V=[C,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
|
||||
N=[C,"abstract,as,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,group,implicit,in,interface,internal,into,is,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],C=[C,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],O=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
|
||||
P=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],Q=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
|
||||
U=/\S/,X=v({keywords:[M,N,C,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",O,P,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(D([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",
|
||||
/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(D([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],
|
||||
["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(D([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:Q}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:N,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:Q}),
|
||||
["cs"]);p(v({keywords:V,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:O,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:P,
|
||||
hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:C,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]);
|
||||
p(D([],[["str",/^[\S\s]+/]]),["regex"]);var Y=E.PR={createSimpleLexer:D,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:E.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1});
|
||||
return b.innerHTML},prettyPrint:E.prettyPrint=function(a,d){function g(){for(var b=E.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i<p.length&&c.now()<b;i++){for(var d=p[i],j=h,k=d;k=k.previousSibling;){var m=k.nodeType,o=(m===7||m===8)&&k.nodeValue;if(o?!/^\??prettify\b/.test(o):m!==3||/\S/.test(k.nodeValue))break;if(o){j={};o.replace(/\b(\w+)=([\w%+\-.:]+)/g,function(a,b,c){j[b]=c});break}}k=d.className;if((j!==h||e.test(k))&&!v.test(k)){m=!1;for(o=d.parentNode;o;o=o.parentNode)if(f.test(o.tagName)&&
|
||||
o.className&&e.test(o.className)){m=!0;break}if(!m){d.className+=" prettyprinted";m=j.lang;if(!m){var m=k.match(n),y;if(!m&&(y=T(d))&&t.test(y.tagName))m=y.className.match(n);m&&(m=m[1])}if(w.test(d.tagName))o=1;else var o=d.currentStyle,u=s.defaultView,o=(o=o?o.whiteSpace:u&&u.getComputedStyle?u.getComputedStyle(d,q).getPropertyValue("white-space"):0)&&"pre"===o.substring(0,3);u=j.linenums;if(!(u=u==="true"||+u))u=(u=k.match(/\blinenums\b(?::(\d+))?/))?u[1]&&u[1].length?+u[1]:!0:!1;u&&J(d,u,o);r=
|
||||
{h:m,c:d,j:u,i:o};K(r)}}}i<p.length?setTimeout(g,250):"function"===typeof a&&a()}for(var b=d||document.body,s=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],p=[],m=0;m<b.length;++m)for(var j=0,k=b[m].length;j<k;++j)p.push(b[m][j]);var b=q,c=Date;c.now||(c={now:function(){return+new Date}});var i=0,r,n=/\blang(?:uage)?-([\w.]+)(?!\S)/,e=/\bprettyprint\b/,v=/\bprettyprinted\b/,w=/pre|xmp/i,t=/^code$/i,f=/^(?:pre|code|xmp)$/i,
|
||||
h={};g()}};typeof define==="function"&&define.amd&&define("google-code-prettify",[],function(){return Y})})();}()
|
@ -1,755 +0,0 @@
|
||||
/*
|
||||
* $Id: rawinflate.js,v 0.3 2013/04/09 14:25:38 dankogai Exp dankogai $
|
||||
*
|
||||
* GNU General Public License, version 2 (GPL-2.0)
|
||||
* https://opensource.org/licenses/GPL-2.0
|
||||
* original:
|
||||
* http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt
|
||||
*/
|
||||
|
||||
(function(ctx){
|
||||
|
||||
/* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
|
||||
* Version: 1.0.0.1
|
||||
* LastModified: Dec 25 1999
|
||||
*/
|
||||
|
||||
/* Interface:
|
||||
* data = zip_inflate(src);
|
||||
*/
|
||||
|
||||
/* constant parameters */
|
||||
var zip_WSIZE = 32768; // Sliding Window size
|
||||
var zip_STORED_BLOCK = 0;
|
||||
var zip_STATIC_TREES = 1;
|
||||
var zip_DYN_TREES = 2;
|
||||
|
||||
/* for inflate */
|
||||
var zip_lbits = 9; // bits in base literal/length lookup table
|
||||
var zip_dbits = 6; // bits in base distance lookup table
|
||||
var zip_INBUFSIZ = 32768; // Input buffer size
|
||||
var zip_INBUF_EXTRA = 64; // Extra buffer
|
||||
|
||||
/* variables (inflate) */
|
||||
var zip_slide;
|
||||
var zip_wp; // current position in slide
|
||||
var zip_fixed_tl = null; // inflate static
|
||||
var zip_fixed_td; // inflate static
|
||||
var zip_fixed_bl, fixed_bd; // inflate static
|
||||
var zip_bit_buf; // bit buffer
|
||||
var zip_bit_len; // bits in bit buffer
|
||||
var zip_method;
|
||||
var zip_eof;
|
||||
var zip_copy_leng;
|
||||
var zip_copy_dist;
|
||||
var zip_tl, zip_td; // literal/length and distance decoder tables
|
||||
var zip_bl, zip_bd; // number of bits decoded by tl and td
|
||||
|
||||
var zip_inflate_data;
|
||||
var zip_inflate_pos;
|
||||
|
||||
|
||||
/* constant tables (inflate) */
|
||||
var zip_MASK_BITS = new Array(
|
||||
0x0000,
|
||||
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
|
||||
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff);
|
||||
// Tables for deflate from PKZIP's appnote.txt.
|
||||
var zip_cplens = new Array( // Copy lengths for literal codes 257..285
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0);
|
||||
/* note: see note #13 above about the 258 in this list. */
|
||||
var zip_cplext = new Array( // Extra bits for literal codes 257..285
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99); // 99==invalid
|
||||
var zip_cpdist = new Array( // Copy offsets for distance codes 0..29
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
8193, 12289, 16385, 24577);
|
||||
var zip_cpdext = new Array( // Extra bits for distance codes
|
||||
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
|
||||
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
||||
12, 12, 13, 13);
|
||||
var zip_border = new Array( // Order of the bit length code lengths
|
||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15);
|
||||
/* objects (inflate) */
|
||||
|
||||
var zip_HuftList = function() {
|
||||
this.next = null;
|
||||
this.list = null;
|
||||
}
|
||||
|
||||
var zip_HuftNode = function() {
|
||||
this.e = 0; // number of extra bits or operation
|
||||
this.b = 0; // number of bits in this code or subcode
|
||||
|
||||
// union
|
||||
this.n = 0; // literal, length base, or distance base
|
||||
this.t = null; // (zip_HuftNode) pointer to next level of table
|
||||
}
|
||||
|
||||
var zip_HuftBuild = function(b, // code lengths in bits (all assumed <= BMAX)
|
||||
n, // number of codes (assumed <= N_MAX)
|
||||
s, // number of simple-valued codes (0..s-1)
|
||||
d, // list of base values for non-simple codes
|
||||
e, // list of extra bits for non-simple codes
|
||||
mm // maximum lookup bits
|
||||
) {
|
||||
this.BMAX = 16; // maximum bit length of any code
|
||||
this.N_MAX = 288; // maximum number of codes in any set
|
||||
this.status = 0; // 0: success, 1: incomplete table, 2: bad input
|
||||
this.root = null; // (zip_HuftList) starting table
|
||||
this.m = 0; // maximum lookup bits, returns actual
|
||||
|
||||
/* Given a list of code lengths and a maximum table size, make a set of
|
||||
tables to decode that set of codes. Return zero on success, one if
|
||||
the given code set is incomplete (the tables are still built in this
|
||||
case), two if the input is invalid (all zero length codes or an
|
||||
oversubscribed set of lengths), and three if not enough memory.
|
||||
The code with value 256 is special, and the tables are constructed
|
||||
so that no bits beyond that code are fetched when that code is
|
||||
decoded. */
|
||||
{
|
||||
var a; // counter for codes of length k
|
||||
var c = new Array(this.BMAX+1); // bit length count table
|
||||
var el; // length of EOB code (value 256)
|
||||
var f; // i repeats in table every f entries
|
||||
var g; // maximum code length
|
||||
var h; // table level
|
||||
var i; // counter, current code
|
||||
var j; // counter
|
||||
var k; // number of bits in current code
|
||||
var lx = new Array(this.BMAX+1); // stack of bits per table
|
||||
var p; // pointer into c[], b[], or v[]
|
||||
var pidx; // index of p
|
||||
var q; // (zip_HuftNode) points to current table
|
||||
var r = new zip_HuftNode(); // table entry for structure assignment
|
||||
var u = new Array(this.BMAX); // zip_HuftNode[BMAX][] table stack
|
||||
var v = new Array(this.N_MAX); // values in order of bit length
|
||||
var w;
|
||||
var x = new Array(this.BMAX+1);// bit offsets, then code stack
|
||||
var xp; // pointer into x or c
|
||||
var y; // number of dummy codes added
|
||||
var z; // number of entries in current table
|
||||
var o;
|
||||
var tail; // (zip_HuftList)
|
||||
|
||||
tail = this.root = null;
|
||||
for(i = 0; i < c.length; i++)
|
||||
c[i] = 0;
|
||||
for(i = 0; i < lx.length; i++)
|
||||
lx[i] = 0;
|
||||
for(i = 0; i < u.length; i++)
|
||||
u[i] = null;
|
||||
for(i = 0; i < v.length; i++)
|
||||
v[i] = 0;
|
||||
for(i = 0; i < x.length; i++)
|
||||
x[i] = 0;
|
||||
|
||||
// Generate counts for each bit length
|
||||
el = n > 256 ? b[256] : this.BMAX; // set length of EOB code, if any
|
||||
p = b; pidx = 0;
|
||||
i = n;
|
||||
do {
|
||||
c[p[pidx]]++; // assume all entries <= BMAX
|
||||
pidx++;
|
||||
} while(--i > 0);
|
||||
if(c[0] == n) { // null input--all zero length codes
|
||||
this.root = null;
|
||||
this.m = 0;
|
||||
this.status = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Find minimum and maximum length, bound *m by those
|
||||
for(j = 1; j <= this.BMAX; j++)
|
||||
if(c[j] != 0)
|
||||
break;
|
||||
k = j; // minimum code length
|
||||
if(mm < j)
|
||||
mm = j;
|
||||
for(i = this.BMAX; i != 0; i--)
|
||||
if(c[i] != 0)
|
||||
break;
|
||||
g = i; // maximum code length
|
||||
if(mm > i)
|
||||
mm = i;
|
||||
|
||||
// Adjust last length count to fill out codes, if needed
|
||||
for(y = 1 << j; j < i; j++, y <<= 1)
|
||||
if((y -= c[j]) < 0) {
|
||||
this.status = 2; // bad input: more codes than bits
|
||||
this.m = mm;
|
||||
return;
|
||||
}
|
||||
if((y -= c[i]) < 0) {
|
||||
this.status = 2;
|
||||
this.m = mm;
|
||||
return;
|
||||
}
|
||||
c[i] += y;
|
||||
|
||||
// Generate starting offsets into the value table for each length
|
||||
x[1] = j = 0;
|
||||
p = c;
|
||||
pidx = 1;
|
||||
xp = 2;
|
||||
while(--i > 0) // note that i == g from above
|
||||
x[xp++] = (j += p[pidx++]);
|
||||
|
||||
// Make a table of values in order of bit lengths
|
||||
p = b; pidx = 0;
|
||||
i = 0;
|
||||
do {
|
||||
if((j = p[pidx++]) != 0)
|
||||
v[x[j]++] = i;
|
||||
} while(++i < n);
|
||||
n = x[g]; // set n to length of v
|
||||
|
||||
// Generate the Huffman codes and for each, make the table entries
|
||||
x[0] = i = 0; // first Huffman code is zero
|
||||
p = v; pidx = 0; // grab values in bit order
|
||||
h = -1; // no tables yet--level -1
|
||||
w = lx[0] = 0; // no bits decoded yet
|
||||
q = null; // ditto
|
||||
z = 0; // ditto
|
||||
|
||||
// go through the bit lengths (k already is bits in shortest code)
|
||||
for(; k <= g; k++) {
|
||||
a = c[k];
|
||||
while(a-- > 0) {
|
||||
// here i is the Huffman code of length k bits for value p[pidx]
|
||||
// make tables up to required level
|
||||
while(k > w + lx[1 + h]) {
|
||||
w += lx[1 + h]; // add bits already decoded
|
||||
h++;
|
||||
|
||||
// compute minimum size table less than or equal to *m bits
|
||||
z = (z = g - w) > mm ? mm : z; // upper limit
|
||||
if((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table
|
||||
// too few codes for k-w bit table
|
||||
f -= a + 1; // deduct codes from patterns left
|
||||
xp = k;
|
||||
while(++j < z) { // try smaller tables up to z bits
|
||||
if((f <<= 1) <= c[++xp])
|
||||
break; // enough codes to use up j bits
|
||||
f -= c[xp]; // else deduct codes from patterns
|
||||
}
|
||||
}
|
||||
if(w + j > el && w < el)
|
||||
j = el - w; // make EOB code end at table
|
||||
z = 1 << j; // table entries for j-bit table
|
||||
lx[1 + h] = j; // set table size in stack
|
||||
|
||||
// allocate and link in new table
|
||||
q = new Array(z);
|
||||
for(o = 0; o < z; o++) {
|
||||
q[o] = new zip_HuftNode();
|
||||
}
|
||||
|
||||
if(tail == null)
|
||||
tail = this.root = new zip_HuftList();
|
||||
else
|
||||
tail = tail.next = new zip_HuftList();
|
||||
tail.next = null;
|
||||
tail.list = q;
|
||||
u[h] = q; // table starts after link
|
||||
|
||||
/* connect to last table, if there is one */
|
||||
if(h > 0) {
|
||||
x[h] = i; // save pattern for backing up
|
||||
r.b = lx[h]; // bits to dump before this table
|
||||
r.e = 16 + j; // bits in this table
|
||||
r.t = q; // pointer to this table
|
||||
j = (i & ((1 << w) - 1)) >> (w - lx[h]);
|
||||
u[h-1][j].e = r.e;
|
||||
u[h-1][j].b = r.b;
|
||||
u[h-1][j].n = r.n;
|
||||
u[h-1][j].t = r.t;
|
||||
}
|
||||
}
|
||||
|
||||
// set up table entry in r
|
||||
r.b = k - w;
|
||||
if(pidx >= n)
|
||||
r.e = 99; // out of values--invalid code
|
||||
else if(p[pidx] < s) {
|
||||
r.e = (p[pidx] < 256 ? 16 : 15); // 256 is end-of-block code
|
||||
r.n = p[pidx++]; // simple code is just the value
|
||||
} else {
|
||||
r.e = e[p[pidx] - s]; // non-simple--look up in lists
|
||||
r.n = d[p[pidx++] - s];
|
||||
}
|
||||
|
||||
// fill code-like entries with r //
|
||||
f = 1 << (k - w);
|
||||
for(j = i >> w; j < z; j += f) {
|
||||
q[j].e = r.e;
|
||||
q[j].b = r.b;
|
||||
q[j].n = r.n;
|
||||
q[j].t = r.t;
|
||||
}
|
||||
|
||||
// backwards increment the k-bit code i
|
||||
for(j = 1 << (k - 1); (i & j) != 0; j >>= 1)
|
||||
i ^= j;
|
||||
i ^= j;
|
||||
|
||||
// backup over finished tables
|
||||
while((i & ((1 << w) - 1)) != x[h]) {
|
||||
w -= lx[h]; // don't need to update q
|
||||
h--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return actual size of base table */
|
||||
this.m = lx[1];
|
||||
|
||||
/* Return true (1) if we were given an incomplete table */
|
||||
this.status = ((y != 0 && g != 1) ? 1 : 0);
|
||||
} /* end of constructor */
|
||||
}
|
||||
|
||||
|
||||
/* routines (inflate) */
|
||||
|
||||
var zip_GET_BYTE = function() {
|
||||
if(zip_inflate_data.length == zip_inflate_pos)
|
||||
return -1;
|
||||
return zip_inflate_data.charCodeAt(zip_inflate_pos++) & 0xff;
|
||||
}
|
||||
|
||||
var zip_NEEDBITS = function(n) {
|
||||
while(zip_bit_len < n) {
|
||||
zip_bit_buf |= zip_GET_BYTE() << zip_bit_len;
|
||||
zip_bit_len += 8;
|
||||
}
|
||||
}
|
||||
|
||||
var zip_GETBITS = function(n) {
|
||||
return zip_bit_buf & zip_MASK_BITS[n];
|
||||
}
|
||||
|
||||
var zip_DUMPBITS = function(n) {
|
||||
zip_bit_buf >>= n;
|
||||
zip_bit_len -= n;
|
||||
}
|
||||
|
||||
var zip_inflate_codes = function(buff, off, size) {
|
||||
/* inflate (decompress) the codes in a deflated (compressed) block.
|
||||
Return an error code or zero if it all goes ok. */
|
||||
var e; // table entry flag/number of extra bits
|
||||
var t; // (zip_HuftNode) pointer to table entry
|
||||
var n;
|
||||
|
||||
if(size == 0)
|
||||
return 0;
|
||||
|
||||
// inflate the coded data
|
||||
n = 0;
|
||||
for(;;) { // do until end of block
|
||||
zip_NEEDBITS(zip_bl);
|
||||
t = zip_tl.list[zip_GETBITS(zip_bl)];
|
||||
e = t.e;
|
||||
while(e > 16) {
|
||||
if(e == 99)
|
||||
return -1;
|
||||
zip_DUMPBITS(t.b);
|
||||
e -= 16;
|
||||
zip_NEEDBITS(e);
|
||||
t = t.t[zip_GETBITS(e)];
|
||||
e = t.e;
|
||||
}
|
||||
zip_DUMPBITS(t.b);
|
||||
|
||||
if(e == 16) { // then it's a literal
|
||||
zip_wp &= zip_WSIZE - 1;
|
||||
buff[off + n++] = zip_slide[zip_wp++] = t.n;
|
||||
if(n == size)
|
||||
return size;
|
||||
continue;
|
||||
}
|
||||
|
||||
// exit if end of block
|
||||
if(e == 15)
|
||||
break;
|
||||
|
||||
// it's an EOB or a length
|
||||
|
||||
// get length of block to copy
|
||||
zip_NEEDBITS(e);
|
||||
zip_copy_leng = t.n + zip_GETBITS(e);
|
||||
zip_DUMPBITS(e);
|
||||
|
||||
// decode distance of block to copy
|
||||
zip_NEEDBITS(zip_bd);
|
||||
t = zip_td.list[zip_GETBITS(zip_bd)];
|
||||
e = t.e;
|
||||
|
||||
while(e > 16) {
|
||||
if(e == 99)
|
||||
return -1;
|
||||
zip_DUMPBITS(t.b);
|
||||
e -= 16;
|
||||
zip_NEEDBITS(e);
|
||||
t = t.t[zip_GETBITS(e)];
|
||||
e = t.e;
|
||||
}
|
||||
zip_DUMPBITS(t.b);
|
||||
zip_NEEDBITS(e);
|
||||
zip_copy_dist = zip_wp - t.n - zip_GETBITS(e);
|
||||
zip_DUMPBITS(e);
|
||||
|
||||
// do the copy
|
||||
while(zip_copy_leng > 0 && n < size) {
|
||||
zip_copy_leng--;
|
||||
zip_copy_dist &= zip_WSIZE - 1;
|
||||
zip_wp &= zip_WSIZE - 1;
|
||||
buff[off + n++] = zip_slide[zip_wp++]
|
||||
= zip_slide[zip_copy_dist++];
|
||||
}
|
||||
|
||||
if(n == size)
|
||||
return size;
|
||||
}
|
||||
|
||||
zip_method = -1; // done
|
||||
return n;
|
||||
}
|
||||
|
||||
var zip_inflate_stored = function(buff, off, size) {
|
||||
/* "decompress" an inflated type 0 (stored) block. */
|
||||
var n;
|
||||
|
||||
// go to byte boundary
|
||||
n = zip_bit_len & 7;
|
||||
zip_DUMPBITS(n);
|
||||
|
||||
// get the length and its complement
|
||||
zip_NEEDBITS(16);
|
||||
n = zip_GETBITS(16);
|
||||
zip_DUMPBITS(16);
|
||||
zip_NEEDBITS(16);
|
||||
if(n != ((~zip_bit_buf) & 0xffff))
|
||||
return -1; // error in compressed data
|
||||
zip_DUMPBITS(16);
|
||||
|
||||
// read and output the compressed data
|
||||
zip_copy_leng = n;
|
||||
|
||||
n = 0;
|
||||
while(zip_copy_leng > 0 && n < size) {
|
||||
zip_copy_leng--;
|
||||
zip_wp &= zip_WSIZE - 1;
|
||||
zip_NEEDBITS(8);
|
||||
buff[off + n++] = zip_slide[zip_wp++] =
|
||||
zip_GETBITS(8);
|
||||
zip_DUMPBITS(8);
|
||||
}
|
||||
|
||||
if(zip_copy_leng == 0)
|
||||
zip_method = -1; // done
|
||||
return n;
|
||||
}
|
||||
|
||||
var zip_inflate_fixed = function(buff, off, size) {
|
||||
/* decompress an inflated type 1 (fixed Huffman codes) block. We should
|
||||
either replace this with a custom decoder, or at least precompute the
|
||||
Huffman tables. */
|
||||
|
||||
// if first time, set up tables for fixed blocks
|
||||
if(zip_fixed_tl == null) {
|
||||
var i; // temporary variable
|
||||
var l = new Array(288); // length list for huft_build
|
||||
var h; // zip_HuftBuild
|
||||
|
||||
// literal table
|
||||
for(i = 0; i < 144; i++)
|
||||
l[i] = 8;
|
||||
for(; i < 256; i++)
|
||||
l[i] = 9;
|
||||
for(; i < 280; i++)
|
||||
l[i] = 7;
|
||||
for(; i < 288; i++) // make a complete, but wrong code set
|
||||
l[i] = 8;
|
||||
zip_fixed_bl = 7;
|
||||
|
||||
h = new zip_HuftBuild(l, 288, 257, zip_cplens, zip_cplext,
|
||||
zip_fixed_bl);
|
||||
if(h.status != 0) {
|
||||
alert("HufBuild error: "+h.status);
|
||||
return -1;
|
||||
}
|
||||
zip_fixed_tl = h.root;
|
||||
zip_fixed_bl = h.m;
|
||||
|
||||
// distance table
|
||||
for(i = 0; i < 30; i++) // make an incomplete code set
|
||||
l[i] = 5;
|
||||
zip_fixed_bd = 5;
|
||||
|
||||
h = new zip_HuftBuild(l, 30, 0, zip_cpdist, zip_cpdext, zip_fixed_bd);
|
||||
if(h.status > 1) {
|
||||
zip_fixed_tl = null;
|
||||
alert("HufBuild error: "+h.status);
|
||||
return -1;
|
||||
}
|
||||
zip_fixed_td = h.root;
|
||||
zip_fixed_bd = h.m;
|
||||
}
|
||||
|
||||
zip_tl = zip_fixed_tl;
|
||||
zip_td = zip_fixed_td;
|
||||
zip_bl = zip_fixed_bl;
|
||||
zip_bd = zip_fixed_bd;
|
||||
return zip_inflate_codes(buff, off, size);
|
||||
}
|
||||
|
||||
var zip_inflate_dynamic = function(buff, off, size) {
|
||||
// decompress an inflated type 2 (dynamic Huffman codes) block.
|
||||
var i; // temporary variables
|
||||
var j;
|
||||
var l; // last length
|
||||
var n; // number of lengths to get
|
||||
var t; // (zip_HuftNode) literal/length code table
|
||||
var nb; // number of bit length codes
|
||||
var nl; // number of literal/length codes
|
||||
var nd; // number of distance codes
|
||||
var ll = new Array(286+30); // literal/length and distance code lengths
|
||||
var h; // (zip_HuftBuild)
|
||||
|
||||
for(i = 0; i < ll.length; i++)
|
||||
ll[i] = 0;
|
||||
|
||||
// read in table lengths
|
||||
zip_NEEDBITS(5);
|
||||
nl = 257 + zip_GETBITS(5); // number of literal/length codes
|
||||
zip_DUMPBITS(5);
|
||||
zip_NEEDBITS(5);
|
||||
nd = 1 + zip_GETBITS(5); // number of distance codes
|
||||
zip_DUMPBITS(5);
|
||||
zip_NEEDBITS(4);
|
||||
nb = 4 + zip_GETBITS(4); // number of bit length codes
|
||||
zip_DUMPBITS(4);
|
||||
if(nl > 286 || nd > 30)
|
||||
return -1; // bad lengths
|
||||
|
||||
// read in bit-length-code lengths
|
||||
for(j = 0; j < nb; j++)
|
||||
{
|
||||
zip_NEEDBITS(3);
|
||||
ll[zip_border[j]] = zip_GETBITS(3);
|
||||
zip_DUMPBITS(3);
|
||||
}
|
||||
for(; j < 19; j++)
|
||||
ll[zip_border[j]] = 0;
|
||||
|
||||
// build decoding table for trees--single level, 7 bit lookup
|
||||
zip_bl = 7;
|
||||
h = new zip_HuftBuild(ll, 19, 19, null, null, zip_bl);
|
||||
if(h.status != 0)
|
||||
return -1; // incomplete code set
|
||||
|
||||
zip_tl = h.root;
|
||||
zip_bl = h.m;
|
||||
|
||||
// read in literal and distance code lengths
|
||||
n = nl + nd;
|
||||
i = l = 0;
|
||||
while(i < n) {
|
||||
zip_NEEDBITS(zip_bl);
|
||||
t = zip_tl.list[zip_GETBITS(zip_bl)];
|
||||
j = t.b;
|
||||
zip_DUMPBITS(j);
|
||||
j = t.n;
|
||||
if(j < 16) // length of code in bits (0..15)
|
||||
ll[i++] = l = j; // save last length in l
|
||||
else if(j == 16) { // repeat last length 3 to 6 times
|
||||
zip_NEEDBITS(2);
|
||||
j = 3 + zip_GETBITS(2);
|
||||
zip_DUMPBITS(2);
|
||||
if(i + j > n)
|
||||
return -1;
|
||||
while(j-- > 0)
|
||||
ll[i++] = l;
|
||||
} else if(j == 17) { // 3 to 10 zero length codes
|
||||
zip_NEEDBITS(3);
|
||||
j = 3 + zip_GETBITS(3);
|
||||
zip_DUMPBITS(3);
|
||||
if(i + j > n)
|
||||
return -1;
|
||||
while(j-- > 0)
|
||||
ll[i++] = 0;
|
||||
l = 0;
|
||||
} else { // j == 18: 11 to 138 zero length codes
|
||||
zip_NEEDBITS(7);
|
||||
j = 11 + zip_GETBITS(7);
|
||||
zip_DUMPBITS(7);
|
||||
if(i + j > n)
|
||||
return -1;
|
||||
while(j-- > 0)
|
||||
ll[i++] = 0;
|
||||
l = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// build the decoding tables for literal/length and distance codes
|
||||
zip_bl = zip_lbits;
|
||||
h = new zip_HuftBuild(ll, nl, 257, zip_cplens, zip_cplext, zip_bl);
|
||||
if(zip_bl == 0) // no literals or lengths
|
||||
h.status = 1;
|
||||
if(h.status != 0) {
|
||||
if(h.status == 1)
|
||||
;// **incomplete literal tree**
|
||||
return -1; // incomplete code set
|
||||
}
|
||||
zip_tl = h.root;
|
||||
zip_bl = h.m;
|
||||
|
||||
for(i = 0; i < nd; i++)
|
||||
ll[i] = ll[i + nl];
|
||||
zip_bd = zip_dbits;
|
||||
h = new zip_HuftBuild(ll, nd, 0, zip_cpdist, zip_cpdext, zip_bd);
|
||||
zip_td = h.root;
|
||||
zip_bd = h.m;
|
||||
|
||||
if(zip_bd == 0 && nl > 257) { // lengths but no distances
|
||||
// **incomplete distance tree**
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(h.status == 1) {
|
||||
;// **incomplete distance tree**
|
||||
}
|
||||
if(h.status != 0)
|
||||
return -1;
|
||||
|
||||
// decompress until an end-of-block code
|
||||
return zip_inflate_codes(buff, off, size);
|
||||
}
|
||||
|
||||
var zip_inflate_start = function() {
|
||||
var i;
|
||||
|
||||
if(zip_slide == null)
|
||||
zip_slide = new Array(2 * zip_WSIZE);
|
||||
zip_wp = 0;
|
||||
zip_bit_buf = 0;
|
||||
zip_bit_len = 0;
|
||||
zip_method = -1;
|
||||
zip_eof = false;
|
||||
zip_copy_leng = zip_copy_dist = 0;
|
||||
zip_tl = null;
|
||||
}
|
||||
|
||||
var zip_inflate_internal = function(buff, off, size) {
|
||||
// decompress an inflated entry
|
||||
var n, i;
|
||||
|
||||
n = 0;
|
||||
while(n < size) {
|
||||
if(zip_eof && zip_method == -1)
|
||||
return n;
|
||||
|
||||
if(zip_copy_leng > 0) {
|
||||
if(zip_method != zip_STORED_BLOCK) {
|
||||
// STATIC_TREES or DYN_TREES
|
||||
while(zip_copy_leng > 0 && n < size) {
|
||||
zip_copy_leng--;
|
||||
zip_copy_dist &= zip_WSIZE - 1;
|
||||
zip_wp &= zip_WSIZE - 1;
|
||||
buff[off + n++] = zip_slide[zip_wp++] =
|
||||
zip_slide[zip_copy_dist++];
|
||||
}
|
||||
} else {
|
||||
while(zip_copy_leng > 0 && n < size) {
|
||||
zip_copy_leng--;
|
||||
zip_wp &= zip_WSIZE - 1;
|
||||
zip_NEEDBITS(8);
|
||||
buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8);
|
||||
zip_DUMPBITS(8);
|
||||
}
|
||||
if(zip_copy_leng == 0)
|
||||
zip_method = -1; // done
|
||||
}
|
||||
if(n == size)
|
||||
return n;
|
||||
}
|
||||
|
||||
if(zip_method == -1) {
|
||||
if(zip_eof)
|
||||
break;
|
||||
|
||||
// read in last block bit
|
||||
zip_NEEDBITS(1);
|
||||
if(zip_GETBITS(1) != 0)
|
||||
zip_eof = true;
|
||||
zip_DUMPBITS(1);
|
||||
|
||||
// read in block type
|
||||
zip_NEEDBITS(2);
|
||||
zip_method = zip_GETBITS(2);
|
||||
zip_DUMPBITS(2);
|
||||
zip_tl = null;
|
||||
zip_copy_leng = 0;
|
||||
}
|
||||
|
||||
switch(zip_method) {
|
||||
case 0: // zip_STORED_BLOCK
|
||||
i = zip_inflate_stored(buff, off + n, size - n);
|
||||
break;
|
||||
|
||||
case 1: // zip_STATIC_TREES
|
||||
if(zip_tl != null)
|
||||
i = zip_inflate_codes(buff, off + n, size - n);
|
||||
else
|
||||
i = zip_inflate_fixed(buff, off + n, size - n);
|
||||
break;
|
||||
|
||||
case 2: // zip_DYN_TREES
|
||||
if(zip_tl != null)
|
||||
i = zip_inflate_codes(buff, off + n, size - n);
|
||||
else
|
||||
i = zip_inflate_dynamic(buff, off + n, size - n);
|
||||
break;
|
||||
|
||||
default: // error
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == -1) {
|
||||
if(zip_eof)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
n += i;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
var zip_inflate = function(str) {
|
||||
var i, j;
|
||||
|
||||
zip_inflate_start();
|
||||
zip_inflate_data = str;
|
||||
zip_inflate_pos = 0;
|
||||
|
||||
var buff = new Array(1024);
|
||||
var aout = [];
|
||||
while((i = zip_inflate_internal(buff, 0, buff.length)) > 0) {
|
||||
var cbuf = new Array(i);
|
||||
for(j = 0; j < i; j++){
|
||||
cbuf[j] = String.fromCharCode(buff[j]);
|
||||
}
|
||||
aout[aout.length] = cbuf.join("");
|
||||
}
|
||||
zip_inflate_data = null; // G.C.
|
||||
return aout.join("");
|
||||
}
|
||||
|
||||
if (! ctx.RawDeflate) ctx.RawDeflate = {};
|
||||
ctx.RawDeflate.inflate = zip_inflate;
|
||||
|
||||
})(this);
|
@ -1,60 +0,0 @@
|
||||
"use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"NOT READY: "+this.message};this.message=a}}};
|
||||
sjcl.cipher.aes=function(a){this.s[0][0][0]||this.O();var b,c,d,e,f=this.s[0][4],g=this.s[1];b=a.length;var h=1;if(4!==b&&6!==b&&8!==b)throw new sjcl.exception.invalid("invalid aes key size");this.b=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(0===a%b||8===b&&4===a%b)c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255],0===a%b&&(c=c<<8^c>>>24^h<<24,h=h<<1^283*(h>>7));d[a]=d[a-b]^c}for(b=0;a;b++,a--)c=d[b&3?a:a-4],e[b]=4>=a||4>b?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^g[3][f[c&
|
||||
255]]};
|
||||
sjcl.cipher.aes.prototype={encrypt:function(a){return t(this,a,0)},decrypt:function(a){return t(this,a,1)},s:[[[],[],[],[],[]],[[],[],[],[],[]]],O:function(){var a=this.s[0],b=this.s[1],c=a[4],d=b[4],e,f,g,h=[],k=[],l,n,m,p;for(e=0;0x100>e;e++)k[(h[e]=e<<1^283*(e>>7))^e]=e;for(f=g=0;!c[f];f^=l||1,g=k[g]||1)for(m=g^g<<1^g<<2^g<<3^g<<4,m=m>>8^m&255^99,c[f]=m,d[m]=f,n=h[e=h[l=h[f]]],p=0x1010101*n^0x10001*e^0x101*l^0x1010100*f,n=0x101*h[m]^0x1010100*m,e=0;4>e;e++)a[e][f]=n=n<<24^n>>>8,b[e][m]=p=p<<24^p>>>8;for(e=
|
||||
0;5>e;e++)a[e]=a[e].slice(0),b[e]=b[e].slice(0)}};
|
||||
function t(a,b,c){if(4!==b.length)throw new sjcl.exception.invalid("invalid aes block size");var d=a.b[c],e=b[0]^d[0],f=b[c?3:1]^d[1],g=b[2]^d[2];b=b[c?1:3]^d[3];var h,k,l,n=d.length/4-2,m,p=4,r=[0,0,0,0];h=a.s[c];a=h[0];var q=h[1],v=h[2],w=h[3],x=h[4];for(m=0;m<n;m++)h=a[e>>>24]^q[f>>16&255]^v[g>>8&255]^w[b&255]^d[p],k=a[f>>>24]^q[g>>16&255]^v[b>>8&255]^w[e&255]^d[p+1],l=a[g>>>24]^q[b>>16&255]^v[e>>8&255]^w[f&255]^d[p+2],b=a[b>>>24]^q[e>>16&255]^v[f>>8&255]^w[g&255]^d[p+3],p+=4,e=h,f=k,g=l;for(m=
|
||||
0;4>m;m++)r[c?3&-m:m]=x[e>>>24]<<24^x[f>>16&255]<<16^x[g>>8&255]<<8^x[b&255]^d[p++],h=e,e=f,f=g,g=b,b=h;return r}
|
||||
sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.$(a.slice(b/32),32-(b&31)).slice(1);return void 0===c?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<<c)-1},concat:function(a,b){if(0===a.length||0===b.length)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return 32===d?a.concat(b):sjcl.bitArray.$(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;return 0===
|
||||
b?0:32*(b-1)+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(32*a.length<b)return a;a=a.slice(0,Math.ceil(b/32));var c=a.length;b=b&31;0<c&&b&&(a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1));return a},partial:function(a,b,c){return 32===a?b:(c?b|0:b<<32-a)+0x10000000000*a},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return!1;var c=0,d;for(d=0;d<a.length;d++)c|=a[d]^b[d];return 0===
|
||||
c},$:function(a,b,c,d){var e;e=0;for(void 0===d&&(d=[]);32<=b;b-=32)d.push(c),c=0;if(0===b)return d.concat(a);for(e=0;e<a.length;e++)d.push(c|a[e]>>>b),c=a[e]<<32-b;e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,32<b+a?c:d.pop(),1));return d},i:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]},byteswapM:function(a){var b,c;for(b=0;b<a.length;++b)c=a[b],a[b]=c>>>24|c>>>8&0xff00|(c&0xff00)<<8|c<<24;return a}};
|
||||
sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d<c/8;d++)0===(d&3)&&(e=a[d/4]),b+=String.fromCharCode(e>>>24),e<<=8;return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c<a.length;c++)d=d<<8|a.charCodeAt(c),3===(c&3)&&(b.push(d),d=0);c&3&&b.push(sjcl.bitArray.partial(8*(c&3),d));return b}};
|
||||
sjcl.codec.hex={fromBits:function(a){var b="",c;for(c=0;c<a.length;c++)b+=((a[c]|0)+0xf00000000000).toString(16).substr(4);return b.substr(0,sjcl.bitArray.bitLength(a)/4)},toBits:function(a){var b,c=[],d;a=a.replace(/\s|0x/g,"");d=a.length;a=a+"00000000";for(b=0;b<a.length;b+=8)c.push(parseInt(a.substr(b,8),16)^0);return sjcl.bitArray.clamp(c,4*d)}};
|
||||
sjcl.codec.base32={B:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",X:"0123456789ABCDEFGHIJKLMNOPQRSTUV",BITS:32,BASE:5,REMAINING:27,fromBits:function(a,b,c){var d=sjcl.codec.base32.BASE,e=sjcl.codec.base32.REMAINING,f="",g=0,h=sjcl.codec.base32.B,k=0,l=sjcl.bitArray.bitLength(a);c&&(h=sjcl.codec.base32.X);for(c=0;f.length*d<l;)f+=h.charAt((k^a[c]>>>g)>>>e),g<d?(k=a[c]<<d-g,g+=e,c++):(k<<=d,g-=d);for(;f.length&7&&!b;)f+="=";return f},toBits:function(a,b){a=a.replace(/\s|=/g,"").toUpperCase();var c=sjcl.codec.base32.BITS,
|
||||
d=sjcl.codec.base32.BASE,e=sjcl.codec.base32.REMAINING,f=[],g,h=0,k=sjcl.codec.base32.B,l=0,n,m="base32";b&&(k=sjcl.codec.base32.X,m="base32hex");for(g=0;g<a.length;g++){n=k.indexOf(a.charAt(g));if(0>n){if(!b)try{return sjcl.codec.base32hex.toBits(a)}catch(p){}throw new sjcl.exception.invalid("this isn't "+m+"!");}h>e?(h-=e,f.push(l^n>>>h),l=n<<c-h):(h+=d,l^=n<<c-h)}h&56&&f.push(sjcl.bitArray.partial(h&56,l,1));return f}};
|
||||
sjcl.codec.base32hex={fromBits:function(a,b){return sjcl.codec.base32.fromBits(a,b,1)},toBits:function(a){return sjcl.codec.base32.toBits(a,1)}};
|
||||
sjcl.codec.base64={B:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b,c){var d="",e=0,f=sjcl.codec.base64.B,g=0,h=sjcl.bitArray.bitLength(a);c&&(f=f.substr(0,62)+"-_");for(c=0;6*d.length<h;)d+=f.charAt((g^a[c]>>>e)>>>26),6>e?(g=a[c]<<6-e,e+=26,c++):(g<<=6,e-=6);for(;d.length&3&&!b;)d+="=";return d},toBits:function(a,b){a=a.replace(/\s|=/g,"");var c=[],d,e=0,f=sjcl.codec.base64.B,g=0,h;b&&(f=f.substr(0,62)+"-_");for(d=0;d<a.length;d++){h=f.indexOf(a.charAt(d));
|
||||
if(0>h)throw new sjcl.exception.invalid("this isn't base64!");26<e?(e-=26,c.push(g^h>>>e),g=h<<32-e):(e+=6,g^=h<<32-e)}e&56&&c.push(sjcl.bitArray.partial(e&56,g,1));return c}};sjcl.codec.base64url={fromBits:function(a){return sjcl.codec.base64.fromBits(a,1,1)},toBits:function(a){return sjcl.codec.base64.toBits(a,1)}};sjcl.hash.sha256=function(a){this.b[0]||this.O();a?(this.F=a.F.slice(0),this.A=a.A.slice(0),this.l=a.l):this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()};
|
||||
sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.F=this.Y.slice(0);this.A=[];this.l=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.A=sjcl.bitArray.concat(this.A,a);b=this.l;a=this.l=b+sjcl.bitArray.bitLength(a);if(0x1fffffffffffff<a)throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");if("undefined"!==typeof Uint32Array){var d=new Uint32Array(c),e=0;for(b=512+b-(512+b&0x1ff);b<=a;b+=512)u(this,d.subarray(16*e,
|
||||
16*(e+1))),e+=1;c.splice(0,16*e)}else for(b=512+b-(512+b&0x1ff);b<=a;b+=512)u(this,c.splice(0,16));return this},finalize:function(){var a,b=this.A,c=this.F,b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.l/0x100000000));for(b.push(this.l|0);b.length;)u(this,b.splice(0,16));this.reset();return c},Y:[],b:[],O:function(){function a(a){return 0x100000000*(a-Math.floor(a))|0}for(var b=0,c=2,d,e;64>b;c++){e=!0;for(d=2;d*d<=c;d++)if(0===c%d){e=
|
||||
!1;break}e&&(8>b&&(this.Y[b]=a(Math.pow(c,.5))),this.b[b]=a(Math.pow(c,1/3)),b++)}}};
|
||||
function u(a,b){var c,d,e,f=a.F,g=a.b,h=f[0],k=f[1],l=f[2],n=f[3],m=f[4],p=f[5],r=f[6],q=f[7];for(c=0;64>c;c++)16>c?d=b[c]:(d=b[c+1&15],e=b[c+14&15],d=b[c&15]=(d>>>7^d>>>18^d>>>3^d<<25^d<<14)+(e>>>17^e>>>19^e>>>10^e<<15^e<<13)+b[c&15]+b[c+9&15]|0),d=d+q+(m>>>6^m>>>11^m>>>25^m<<26^m<<21^m<<7)+(r^m&(p^r))+g[c],q=r,r=p,p=m,m=n+d|0,n=l,l=k,k=h,h=d+(k&l^n&(k^l))+(k>>>2^k>>>13^k>>>22^k<<30^k<<19^k<<10)|0;f[0]=f[0]+h|0;f[1]=f[1]+k|0;f[2]=f[2]+l|0;f[3]=f[3]+n|0;f[4]=f[4]+m|0;f[5]=f[5]+p|0;f[6]=f[6]+r|0;f[7]=
|
||||
f[7]+q|0}
|
||||
sjcl.mode.ccm={name:"ccm",G:[],listenProgress:function(a){sjcl.mode.ccm.G.push(a)},unListenProgress:function(a){a=sjcl.mode.ccm.G.indexOf(a);-1<a&&sjcl.mode.ccm.G.splice(a,1)},fa:function(a){var b=sjcl.mode.ccm.G.slice(),c;for(c=0;c<b.length;c+=1)b[c](a)},encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,k=h.bitLength(c)/8,l=h.bitLength(g)/8;e=e||64;d=d||[];if(7>k)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;4>f&&l>>>8*f;f++);f<15-k&&(f=15-k);c=h.clamp(c,
|
||||
8*(15-f));b=sjcl.mode.ccm.V(a,b,c,d,e,f);g=sjcl.mode.ccm.C(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),k=f.clamp(b,h-e),l=f.bitSlice(b,h-e),h=(h-e)/8;if(7>g)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;4>b&&h>>>8*b;b++);b<15-g&&(b=15-g);c=f.clamp(c,8*(15-b));k=sjcl.mode.ccm.C(a,k,c,l,e,b);a=sjcl.mode.ccm.V(a,k.data,c,d,e,b);if(!f.equal(k.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");
|
||||
return k.data},na:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,k=h.i;d=[h.partial(8,(b.length?64:0)|d-2<<2|f-1)];d=h.concat(d,c);d[3]|=e;d=a.encrypt(d);if(b.length)for(c=h.bitLength(b)/8,65279>=c?g=[h.partial(16,c)]:0xffffffff>=c&&(g=h.concat([h.partial(16,65534)],[c])),g=h.concat(g,b),b=0;b<g.length;b+=4)d=a.encrypt(k(d,g.slice(b,b+4).concat([0,0,0])));return d},V:function(a,b,c,d,e,f){var g=sjcl.bitArray,h=g.i;e/=8;if(e%2||4>e||16<e)throw new sjcl.exception.invalid("ccm: invalid tag length");
|
||||
if(0xffffffff<d.length||0xffffffff<b.length)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");c=sjcl.mode.ccm.na(a,d,c,e,g.bitLength(b)/8,f);for(d=0;d<b.length;d+=4)c=a.encrypt(h(c,b.slice(d,d+4).concat([0,0,0])));return g.clamp(c,8*e)},C:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.i;var k=b.length,l=h.bitLength(b),n=k/50,m=n;c=h.concat([h.partial(8,f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!k)return{tag:d,data:[]};for(g=0;g<k;g+=4)g>n&&(sjcl.mode.ccm.fa(g/
|
||||
k),n+=m),c[3]++,e=a.encrypt(c),b[g]^=e[0],b[g+1]^=e[1],b[g+2]^=e[2],b[g+3]^=e[3];return{tag:d,data:h.clamp(b,l)}}};
|
||||
sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){if(128!==sjcl.bitArray.bitLength(c))throw new sjcl.exception.invalid("ocb iv must be 128 bits");var g,h=sjcl.mode.ocb2.S,k=sjcl.bitArray,l=k.i,n=[0,0,0,0];c=h(a.encrypt(c));var m,p=[];d=d||[];e=e||64;for(g=0;g+4<b.length;g+=4)m=b.slice(g,g+4),n=l(n,m),p=p.concat(l(c,a.encrypt(l(c,m)))),c=h(c);m=b.slice(g);b=k.bitLength(m);g=a.encrypt(l(c,[0,0,0,b]));m=k.clamp(l(m.concat([0,0,0]),g),b);n=l(n,l(m.concat([0,0,0]),g));n=a.encrypt(l(n,l(c,h(c))));
|
||||
d.length&&(n=l(n,f?d:sjcl.mode.ocb2.pmac(a,d)));return p.concat(k.concat(m,k.clamp(n,e)))},decrypt:function(a,b,c,d,e,f){if(128!==sjcl.bitArray.bitLength(c))throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.S,h=sjcl.bitArray,k=h.i,l=[0,0,0,0],n=g(a.encrypt(c)),m,p,r=sjcl.bitArray.bitLength(b)-e,q=[];d=d||[];for(c=0;c+4<r/32;c+=4)m=k(n,a.decrypt(k(n,b.slice(c,c+4)))),l=k(l,m),q=q.concat(m),n=g(n);p=r-32*c;m=a.encrypt(k(n,[0,0,0,p]));m=k(m,h.clamp(b.slice(c),p).concat([0,
|
||||
0,0]));l=k(l,m);l=a.encrypt(k(l,k(n,g(n))));d.length&&(l=k(l,f?d:sjcl.mode.ocb2.pmac(a,d)));if(!h.equal(h.clamp(l,e),h.bitSlice(b,r)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return q.concat(h.clamp(m,p))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.S,e=sjcl.bitArray,f=e.i,g=[0,0,0,0],h=a.encrypt([0,0,0,0]),h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4)h=d(h),g=f(g,a.encrypt(f(h,b.slice(c,c+4))));c=b.slice(c);128>e.bitLength(c)&&(h=f(h,d(h)),c=e.concat(c,[-2147483648,0,0,0]));g=f(g,c);
|
||||
return a.encrypt(f(d(f(h,d(h))),g))},S:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^135*(a[0]>>>31)]}};
|
||||
sjcl.mode.gcm={name:"gcm",encrypt:function(a,b,c,d,e){var f=b.slice(0);b=sjcl.bitArray;d=d||[];a=sjcl.mode.gcm.C(!0,a,f,d,c,e||128);return b.concat(a.data,a.tag)},decrypt:function(a,b,c,d,e){var f=b.slice(0),g=sjcl.bitArray,h=g.bitLength(f);e=e||128;d=d||[];e<=h?(b=g.bitSlice(f,h-e),f=g.bitSlice(f,0,h-e)):(b=f,f=[]);a=sjcl.mode.gcm.C(!1,a,f,d,c,e);if(!g.equal(a.tag,b))throw new sjcl.exception.corrupt("gcm: tag doesn't match");return a.data},ka:function(a,b){var c,d,e,f,g,h=sjcl.bitArray.i;e=[0,0,
|
||||
0,0];f=b.slice(0);for(c=0;128>c;c++){(d=0!==(a[Math.floor(c/32)]&1<<31-c%32))&&(e=h(e,f));g=0!==(f[3]&1);for(d=3;0<d;d--)f[d]=f[d]>>>1|(f[d-1]&1)<<31;f[0]>>>=1;g&&(f[0]^=-0x1f000000)}return e},j:function(a,b,c){var d,e=c.length;b=b.slice(0);for(d=0;d<e;d+=4)b[0]^=0xffffffff&c[d],b[1]^=0xffffffff&c[d+1],b[2]^=0xffffffff&c[d+2],b[3]^=0xffffffff&c[d+3],b=sjcl.mode.gcm.ka(b,a);return b},C:function(a,b,c,d,e,f){var g,h,k,l,n,m,p,r,q=sjcl.bitArray;m=c.length;p=q.bitLength(c);r=q.bitLength(d);h=q.bitLength(e);
|
||||
g=b.encrypt([0,0,0,0]);96===h?(e=e.slice(0),e=q.concat(e,[1])):(e=sjcl.mode.gcm.j(g,[0,0,0,0],e),e=sjcl.mode.gcm.j(g,e,[0,0,Math.floor(h/0x100000000),h&0xffffffff]));h=sjcl.mode.gcm.j(g,[0,0,0,0],d);n=e.slice(0);d=h.slice(0);a||(d=sjcl.mode.gcm.j(g,h,c));for(l=0;l<m;l+=4)n[3]++,k=b.encrypt(n),c[l]^=k[0],c[l+1]^=k[1],c[l+2]^=k[2],c[l+3]^=k[3];c=q.clamp(c,p);a&&(d=sjcl.mode.gcm.j(g,h,c));a=[Math.floor(r/0x100000000),r&0xffffffff,Math.floor(p/0x100000000),p&0xffffffff];d=sjcl.mode.gcm.j(g,d,a);k=b.encrypt(e);
|
||||
d[0]^=k[0];d[1]^=k[1];d[2]^=k[2];d[3]^=k[3];return{tag:q.bitSlice(d,0,f),data:c}}};sjcl.misc.hmac=function(a,b){this.W=b=b||sjcl.hash.sha256;var c=[[],[]],d,e=b.prototype.blockSize/32;this.w=[new b,new b];a.length>e&&(a=b.hash(a));for(d=0;d<e;d++)c[0][d]=a[d]^909522486,c[1][d]=a[d]^1549556828;this.w[0].update(c[0]);this.w[1].update(c[1]);this.R=new b(this.w[0])};
|
||||
sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a){if(this.aa)throw new sjcl.exception.invalid("encrypt on already updated hmac called!");this.update(a);return this.digest(a)};sjcl.misc.hmac.prototype.reset=function(){this.R=new this.W(this.w[0]);this.aa=!1};sjcl.misc.hmac.prototype.update=function(a){this.aa=!0;this.R.update(a)};sjcl.misc.hmac.prototype.digest=function(){var a=this.R.finalize(),a=(new this.W(this.w[1])).update(a).finalize();this.reset();return a};
|
||||
sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E4;if(0>d||0>c)throw new sjcl.exception.invalid("invalid params to pbkdf2");"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,k,l=[],n=sjcl.bitArray;for(k=1;32*l.length<(d||1);k++){e=f=a.encrypt(n.concat(b,[k]));for(g=1;g<c;g++)for(f=a.encrypt(f),h=0;h<f.length;h++)e[h]^=f[h];l=l.concat(e)}d&&(l=n.clamp(l,d));return l};
|
||||
sjcl.prng=function(a){this.c=[new sjcl.hash.sha256];this.m=[0];this.P=0;this.H={};this.N=0;this.U={};this.Z=this.f=this.o=this.ha=0;this.b=[0,0,0,0,0,0,0,0];this.h=[0,0,0,0];this.L=void 0;this.M=a;this.D=!1;this.K={progress:{},seeded:{}};this.u=this.ga=0;this.I=1;this.J=2;this.ca=0x10000;this.T=[0,48,64,96,128,192,0x100,384,512,768,1024];this.da=3E4;this.ba=80};
|
||||
sjcl.prng.prototype={randomWords:function(a,b){var c=[],d;d=this.isReady(b);var e;if(d===this.u)throw new sjcl.exception.notReady("generator isn't seeded");if(d&this.J){d=!(d&this.I);e=[];var f=0,g;this.Z=e[0]=(new Date).valueOf()+this.da;for(g=0;16>g;g++)e.push(0x100000000*Math.random()|0);for(g=0;g<this.c.length&&(e=e.concat(this.c[g].finalize()),f+=this.m[g],this.m[g]=0,d||!(this.P&1<<g));g++);this.P>=1<<this.c.length&&(this.c.push(new sjcl.hash.sha256),this.m.push(0));this.f-=f;f>this.o&&(this.o=
|
||||
f);this.P++;this.b=sjcl.hash.sha256.hash(this.b.concat(e));this.L=new sjcl.cipher.aes(this.b);for(d=0;4>d&&(this.h[d]=this.h[d]+1|0,!this.h[d]);d++);}for(d=0;d<a;d+=4)0===(d+1)%this.ca&&y(this),e=z(this),c.push(e[0],e[1],e[2],e[3]);y(this);return c.slice(0,a)},setDefaultParanoia:function(a,b){if(0===a&&"Setting paranoia=0 will ruin your security; use it only for testing"!==b)throw new sjcl.exception.invalid("Setting paranoia=0 will ruin your security; use it only for testing");this.M=a},addEntropy:function(a,
|
||||
b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.H[c],h=this.isReady(),k=0;d=this.U[c];void 0===d&&(d=this.U[c]=this.ha++);void 0===g&&(g=this.H[c]=0);this.H[c]=(this.H[c]+1)%this.c.length;switch(typeof a){case "number":void 0===b&&(b=1);this.c[g].update([d,this.N++,1,b,f,1,a|0]);break;case "object":c=Object.prototype.toString.call(a);if("[object Uint32Array]"===c){e=[];for(c=0;c<a.length;c++)e.push(a[c]);a=e}else for("[object Array]"!==c&&(k=1),c=0;c<a.length&&!k;c++)"number"!==typeof a[c]&&
|
||||
(k=1);if(!k){if(void 0===b)for(c=b=0;c<a.length;c++)for(e=a[c];0<e;)b++,e=e>>>1;this.c[g].update([d,this.N++,2,b,f,a.length].concat(a))}break;case "string":void 0===b&&(b=a.length);this.c[g].update([d,this.N++,3,b,f,a.length]);this.c[g].update(a);break;default:k=1}if(k)throw new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string");this.m[g]+=b;this.f+=b;h===this.u&&(this.isReady()!==this.u&&A("seeded",Math.max(this.o,this.f)),A("progress",this.getProgress()))},
|
||||
isReady:function(a){a=this.T[void 0!==a?a:this.M];return this.o&&this.o>=a?this.m[0]>this.ba&&(new Date).valueOf()>this.Z?this.J|this.I:this.I:this.f>=a?this.J|this.u:this.u},getProgress:function(a){a=this.T[a?a:this.M];return this.o>=a?1:this.f>a?1:this.f/a},startCollectors:function(){if(!this.D){this.a={loadTimeCollector:B(this,this.ma),mouseCollector:B(this,this.oa),keyboardCollector:B(this,this.la),accelerometerCollector:B(this,this.ea),touchCollector:B(this,this.qa)};if(window.addEventListener)window.addEventListener("load",
|
||||
this.a.loadTimeCollector,!1),window.addEventListener("mousemove",this.a.mouseCollector,!1),window.addEventListener("keypress",this.a.keyboardCollector,!1),window.addEventListener("devicemotion",this.a.accelerometerCollector,!1),window.addEventListener("touchmove",this.a.touchCollector,!1);else if(document.attachEvent)document.attachEvent("onload",this.a.loadTimeCollector),document.attachEvent("onmousemove",this.a.mouseCollector),document.attachEvent("keypress",this.a.keyboardCollector);else throw new sjcl.exception.bug("can't attach event");
|
||||
this.D=!0}},stopCollectors:function(){this.D&&(window.removeEventListener?(window.removeEventListener("load",this.a.loadTimeCollector,!1),window.removeEventListener("mousemove",this.a.mouseCollector,!1),window.removeEventListener("keypress",this.a.keyboardCollector,!1),window.removeEventListener("devicemotion",this.a.accelerometerCollector,!1),window.removeEventListener("touchmove",this.a.touchCollector,!1)):document.detachEvent&&(document.detachEvent("onload",this.a.loadTimeCollector),document.detachEvent("onmousemove",
|
||||
this.a.mouseCollector),document.detachEvent("keypress",this.a.keyboardCollector)),this.D=!1)},addEventListener:function(a,b){this.K[a][this.ga++]=b},removeEventListener:function(a,b){var c,d,e=this.K[a],f=[];for(d in e)e.hasOwnProperty(d)&&e[d]===b&&f.push(d);for(c=0;c<f.length;c++)d=f[c],delete e[d]},la:function(){C(this,1)},oa:function(a){var b,c;try{b=a.x||a.clientX||a.offsetX||0,c=a.y||a.clientY||a.offsetY||0}catch(d){c=b=0}0!=b&&0!=c&&this.addEntropy([b,c],2,"mouse");C(this,0)},qa:function(a){a=
|
||||
a.touches[0]||a.changedTouches[0];this.addEntropy([a.pageX||a.clientX,a.pageY||a.clientY],1,"touch");C(this,0)},ma:function(){C(this,2)},ea:function(a){a=a.accelerationIncludingGravity.x||a.accelerationIncludingGravity.y||a.accelerationIncludingGravity.z;if(window.orientation){var b=window.orientation;"number"===typeof b&&this.addEntropy(b,1,"accelerometer")}a&&this.addEntropy(a,2,"accelerometer");C(this,0)}};
|
||||
function A(a,b){var c,d=sjcl.random.K[a],e=[];for(c in d)d.hasOwnProperty(c)&&e.push(d[c]);for(c=0;c<e.length;c++)e[c](b)}function C(a,b){"undefined"!==typeof window&&window.performance&&"function"===typeof window.performance.now?a.addEntropy(window.performance.now(),b,"loadtime"):a.addEntropy((new Date).valueOf(),b,"loadtime")}function y(a){a.b=z(a).concat(z(a));a.L=new sjcl.cipher.aes(a.b)}function z(a){for(var b=0;4>b&&(a.h[b]=a.h[b]+1|0,!a.h[b]);b++);return a.L.encrypt(a.h)}
|
||||
function B(a,b){return function(){b.apply(a,arguments)}}sjcl.random=new sjcl.prng(6);
|
||||
a:try{var D,E,F,G;if(G="undefined"!==typeof module&&module.exports){var H;try{H=require("crypto")}catch(a){H=null}G=E=H}if(G&&E.randomBytes)D=E.randomBytes(128),D=new Uint32Array((new Uint8Array(D)).buffer),sjcl.random.addEntropy(D,1024,"crypto['randomBytes']");else if("undefined"!==typeof window&&"undefined"!==typeof Uint32Array){F=new Uint32Array(32);if(window.crypto&&window.crypto.getRandomValues)window.crypto.getRandomValues(F);else if(window.msCrypto&&window.msCrypto.getRandomValues)window.msCrypto.getRandomValues(F);
|
||||
else break a;sjcl.random.addEntropy(F,1024,"crypto['getRandomValues']")}}catch(a){"undefined"!==typeof window&&window.console&&(console.log("There was an error collecting entropy from the browser:"),console.log(a))}
|
||||
sjcl.json={defaults:{v:1,iter:1E4,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},ja:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.g({iv:sjcl.random.randomWords(4,0)},e.defaults),g;e.g(f,c);c=f.adata;"string"===typeof f.salt&&(f.salt=sjcl.codec.base64.toBits(f.salt));"string"===typeof f.iv&&(f.iv=sjcl.codec.base64.toBits(f.iv));if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||"string"===typeof a&&100>=f.iter||64!==f.ts&&96!==f.ts&&128!==f.ts||128!==f.ks&&192!==f.ks&&0x100!==f.ks||2>f.iv.length||
|
||||
4<f.iv.length)throw new sjcl.exception.invalid("json encrypt: invalid parameters");"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,f),a=g.key.slice(0,f.ks/32),f.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.publicKey&&(g=a.kem(),f.kemtag=g.tag,a=g.key.slice(0,f.ks/32));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));"string"===typeof c&&(f.adata=c=sjcl.codec.utf8String.toBits(c));g=new sjcl.cipher[f.cipher](a);e.g(d,f);d.key=a;f.ct="ccm"===f.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&
|
||||
b instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.encrypt(g,b,f.iv,c,f.ts):sjcl.mode[f.mode].encrypt(g,b,f.iv,c,f.ts);return f},encrypt:function(a,b,c,d){var e=sjcl.json,f=e.ja.apply(e,arguments);return e.encode(f)},ia:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.g(e.g(e.g({},e.defaults),b),c,!0);var f,g;f=b.adata;"string"===typeof b.salt&&(b.salt=sjcl.codec.base64.toBits(b.salt));"string"===typeof b.iv&&(b.iv=sjcl.codec.base64.toBits(b.iv));if(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||"string"===
|
||||
typeof a&&100>=b.iter||64!==b.ts&&96!==b.ts&&128!==b.ts||128!==b.ks&&192!==b.ks&&0x100!==b.ks||!b.iv||2>b.iv.length||4<b.iv.length)throw new sjcl.exception.invalid("json decrypt: invalid parameters");"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,b),a=g.key.slice(0,b.ks/32),b.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.secretKey&&(a=a.unkem(sjcl.codec.base64.toBits(b.kemtag)).slice(0,b.ks/32));"string"===typeof f&&(f=sjcl.codec.utf8String.toBits(f));g=new sjcl.cipher[b.cipher](a);f="ccm"===
|
||||
b.mode&&sjcl.arrayBuffer&&sjcl.arrayBuffer.ccm&&b.ct instanceof ArrayBuffer?sjcl.arrayBuffer.ccm.decrypt(g,b.ct,b.iv,b.tag,f,b.ts):sjcl.mode[b.mode].decrypt(g,b.ct,b.iv,f,b.ts);e.g(d,b);d.key=a;return 1===c.raw?f:sjcl.codec.utf8String.fromBits(f)},decrypt:function(a,b,c,d){var e=sjcl.json;return e.ia(a,e.decode(b),c,d)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b)){if(!b.match(/^[a-z0-9]+$/i))throw new sjcl.exception.invalid("json encode: invalid property name");c+=d+'"'+
|
||||
b+'":';d=",";switch(typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+sjcl.codec.base64.fromBits(a[b],0)+'"';break;default:throw new sjcl.exception.bug("json encode: unsupported type");}}return c+"}"},decode:function(a){a=a.replace(/\s/g,"");if(!a.match(/^\{.*\}$/))throw new sjcl.exception.invalid("json decode: this isn't json!");a=a.replace(/^\{|\}$/g,"").split(/,/);var b={},c,d;for(c=0;c<a.length;c++){if(!(d=a[c].match(/^\s*(?:(["']?)([a-z][a-z0-9]*)\1)\s*:\s*(?:(-?\d+)|"([a-z0-9+\/%*_.@=\-]*)"|(true|false))$/i)))throw new sjcl.exception.invalid("json decode: this isn't json!");
|
||||
null!=d[3]?b[d[2]]=parseInt(d[3],10):null!=d[4]?b[d[2]]=d[2].match(/^(ct|adata|salt|iv)$/)?sjcl.codec.base64.toBits(d[4]):unescape(d[4]):null!=d[5]&&(b[d[2]]="true"===d[5])}return b},g:function(a,b,c){void 0===a&&(a={});if(void 0===b)return a;for(var d in b)if(b.hasOwnProperty(d)){if(c&&void 0!==a[d]&&a[d]!==b[d])throw new sjcl.exception.invalid("required parameter overridden");a[d]=b[d]}return a},sa:function(a,b){var c={},d;for(d in a)a.hasOwnProperty(d)&&a[d]!==b[d]&&(c[d]=a[d]);return c},ra:function(a,
|
||||
b){var c={},d;for(d=0;d<b.length;d++)void 0!==a[b[d]]&&(c[b[d]]=a[b[d]]);return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.pa={};sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.pa,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=void 0===b.salt?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}};
|
||||
"undefined"!==typeof module&&module.exports&&(module.exports=sjcl);"function"===typeof define&&define([],function(){return sjcl});
|
@ -1,158 +0,0 @@
|
||||
'use strict';
|
||||
var jsc = require('jsverify'),
|
||||
jsdom = require('jsdom-global'),
|
||||
cleanup = jsdom(),
|
||||
|
||||
a2zString = ['a','b','c','d','e','f','g','h','i','j','k','l','m',
|
||||
'n','o','p','q','r','s','t','u','v','w','x','y','z'],
|
||||
alnumString = a2zString.concat(['0','1','2','3','4','5','6','7','8','9']),
|
||||
queryString = alnumString.concat(['+','%','&','.','*','-','_']),
|
||||
base64String = alnumString.concat(['+','/','=']).concat(
|
||||
a2zString.map(function(c) {
|
||||
return c.toUpperCase();
|
||||
})
|
||||
);
|
||||
|
||||
global.$ = global.jQuery = require('./jquery-3.1.1');
|
||||
global.sjcl = require('./sjcl-1.0.6');
|
||||
global.Base64 = require('./base64-2.1.9');
|
||||
global.RawDeflate = require('./rawdeflate-0.5');
|
||||
require('./rawinflate-0.3');
|
||||
require('./privatebin');
|
||||
|
||||
describe('helper', function () {
|
||||
describe('secondsToHuman', function () {
|
||||
after(function () {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
jsc.property('returns an array with a number and a word', 'integer', function (number) {
|
||||
var result = $.PrivateBin.helper.secondsToHuman(number);
|
||||
return Array.isArray(result) &&
|
||||
result.length === 2 &&
|
||||
result[0] === parseInt(result[0], 10) &&
|
||||
typeof result[1] === 'string';
|
||||
});
|
||||
jsc.property('returns seconds on the first array position', 'integer 59', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[0] === number;
|
||||
});
|
||||
jsc.property('returns seconds on the second array position', 'integer 59', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'second';
|
||||
});
|
||||
jsc.property('returns minutes on the first array position', 'integer 60 3599', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[0] === Math.floor(number / 60);
|
||||
});
|
||||
jsc.property('returns minutes on the second array position', 'integer 60 3599', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'minute';
|
||||
});
|
||||
jsc.property('returns hours on the first array position', 'integer 3600 86399', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[0] === Math.floor(number / (60 * 60));
|
||||
});
|
||||
jsc.property('returns hours on the second array position', 'integer 3600 86399', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'hour';
|
||||
});
|
||||
jsc.property('returns days on the first array position', 'integer 86400 5184000', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[0] === Math.floor(number / (60 * 60 * 24));
|
||||
});
|
||||
jsc.property('returns days on the second array position', 'integer 86400 5184000', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'day';
|
||||
});
|
||||
// max safe integer as per http://ecma262-5.com/ELS5_HTML.htm#Section_8.5
|
||||
jsc.property('returns months on the first array position', 'integer 5184000 9007199254740991', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[0] === Math.floor(number / (60 * 60 * 24 * 30));
|
||||
});
|
||||
jsc.property('returns months on the second array position', 'integer 5184000 9007199254740991', function (number) {
|
||||
return $.PrivateBin.helper.secondsToHuman(number)[1] === 'month';
|
||||
});
|
||||
});
|
||||
|
||||
describe('scriptLocation', function () {
|
||||
jsc.property(
|
||||
'returns the URL without query & fragment',
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.array(jsc.elements(queryString)),
|
||||
'string',
|
||||
function (schema, address, query, fragment) {
|
||||
var expected = schema.join('') + '://' + address.join('') + '/',
|
||||
clean = jsdom('', {url: expected + '?' + query.join('') + '#' + fragment}),
|
||||
result = $.PrivateBin.helper.scriptLocation();
|
||||
clean();
|
||||
return expected === result;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('pasteId', function () {
|
||||
jsc.property(
|
||||
'returns the query string without separator, if any',
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.array(jsc.elements(queryString)),
|
||||
'string',
|
||||
function (schema, address, query, fragment) {
|
||||
var queryString = query.join(''),
|
||||
clean = jsdom('', {
|
||||
url: schema.join('') + '://' + address.join('') +
|
||||
'/?' + queryString + '#' + fragment
|
||||
}),
|
||||
result = $.PrivateBin.helper.pasteId();
|
||||
clean();
|
||||
return queryString === result;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('pageKey', function () {
|
||||
jsc.property(
|
||||
'returns the fragment of the URL',
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.array(jsc.elements(queryString)),
|
||||
jsc.array(jsc.elements(base64String)),
|
||||
function (schema, address, query, fragment) {
|
||||
var fragmentString = fragment.join(''),
|
||||
clean = jsdom('', {
|
||||
url: schema.join('') + '://' + address.join('') +
|
||||
'/?' + query.join('') + '#' + fragmentString
|
||||
}),
|
||||
result = $.PrivateBin.helper.pageKey();
|
||||
clean();
|
||||
return fragmentString === result;
|
||||
}
|
||||
);
|
||||
jsc.property(
|
||||
'returns the fragment stripped of trailing query parts',
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.array(jsc.elements(queryString)),
|
||||
jsc.array(jsc.elements(base64String)),
|
||||
jsc.array(jsc.elements(queryString)),
|
||||
function (schema, address, query, fragment, trail) {
|
||||
var fragmentString = fragment.join(''),
|
||||
clean = jsdom('', {
|
||||
url: schema.join('') + '://' + address.join('') + '/?' +
|
||||
query.join('') + '#' + fragmentString + '&' + trail.join('')
|
||||
}),
|
||||
result = $.PrivateBin.helper.pageKey();
|
||||
clean();
|
||||
return fragmentString === result;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('htmlEntities', function () {
|
||||
after(function () {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
jsc.property(
|
||||
'removes all HTML entities from any given string',
|
||||
'string',
|
||||
function (string) {
|
||||
var result = $.PrivateBin.helper.htmlEntities(string);
|
||||
return !(/[<>"'`=\/]/.test(result)) && !(string.indexOf('&') > -1 && !(/&/.test(result)));
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
@ -1,2 +0,0 @@
|
||||
Allow from none
|
||||
Deny from all
|
@ -1,247 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* 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
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
namespace PrivateBin;
|
||||
|
||||
use Exception;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
*
|
||||
* parses configuration file, ensures default values present
|
||||
*/
|
||||
class Configuration
|
||||
{
|
||||
/**
|
||||
* parsed configuration
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_configuration;
|
||||
|
||||
/**
|
||||
* default configuration
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $_defaults = array(
|
||||
'main' => array(
|
||||
'name' => 'PrivateBin',
|
||||
'discussion' => true,
|
||||
'opendiscussion' => false,
|
||||
'password' => true,
|
||||
'fileupload' => false,
|
||||
'burnafterreadingselected' => false,
|
||||
'defaultformatter' => 'plaintext',
|
||||
'syntaxhighlightingtheme' => null,
|
||||
'sizelimit' => 2097152,
|
||||
'template' => 'bootstrap',
|
||||
'notice' => '',
|
||||
'languageselection' => false,
|
||||
'languagedefault' => '',
|
||||
'urlshortener' => '',
|
||||
'icon' => 'identicon',
|
||||
'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src *; script-src \'self\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data:; referrer no-referrer; sandbox allow-same-origin allow-scripts allow-forms allow-popups',
|
||||
'zerobincompatibility' => false,
|
||||
),
|
||||
'expire' => array(
|
||||
'default' => '1week',
|
||||
'clone' => true,
|
||||
),
|
||||
'expire_options' => array(
|
||||
'5min' => 300,
|
||||
'10min' => 600,
|
||||
'1hour' => 3600,
|
||||
'1day' => 86400,
|
||||
'1week' => 604800,
|
||||
'1month' => 2592000,
|
||||
'1year' => 31536000,
|
||||
'never' => 0,
|
||||
),
|
||||
'formatter_options' => array(
|
||||
'plaintext' => 'Plain Text',
|
||||
'syntaxhighlighting' => 'Source Code',
|
||||
'markdown' => 'Markdown',
|
||||
),
|
||||
'traffic' => array(
|
||||
'limit' => 10,
|
||||
'header' => null,
|
||||
'dir' => 'data',
|
||||
),
|
||||
'purge' => array(
|
||||
'limit' => 300,
|
||||
'batchsize' => 10,
|
||||
'dir' => 'data',
|
||||
),
|
||||
'model' => array(
|
||||
'class' => 'Filesystem',
|
||||
),
|
||||
'model_options' => array(
|
||||
'dir' => 'data',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* parse configuration file and ensure default configuration values are present
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$config = array();
|
||||
$configFile = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini';
|
||||
if (is_readable($configFile)) {
|
||||
$config = parse_ini_file($configFile, true);
|
||||
foreach (array('main', 'model', 'model_options') as $section) {
|
||||
if (!array_key_exists($section, $config)) {
|
||||
throw new Exception(I18n::_('PrivateBin requires configuration section [%s] to be present in configuration file.', $section), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
$opts = '_options';
|
||||
foreach (self::getDefaults() as $section => $values) {
|
||||
// fill missing sections with default values
|
||||
if (!array_key_exists($section, $config) || count($config[$section]) == 0) {
|
||||
$this->_configuration[$section] = $values;
|
||||
if (array_key_exists('dir', $this->_configuration[$section])) {
|
||||
$this->_configuration[$section]['dir'] = PATH . $this->_configuration[$section]['dir'];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// provide different defaults for database model
|
||||
elseif (
|
||||
$section == 'model_options' && in_array(
|
||||
$this->_configuration['model']['class'],
|
||||
array('Database', 'privatebin_db', 'zerobin_db')
|
||||
)
|
||||
) {
|
||||
$values = array(
|
||||
'dsn' => 'sqlite:' . PATH . 'data' . DIRECTORY_SEPARATOR . 'db.sq3',
|
||||
'tbl' => null,
|
||||
'usr' => null,
|
||||
'pwd' => null,
|
||||
'opt' => array(PDO::ATTR_PERSISTENT => true),
|
||||
);
|
||||
}
|
||||
|
||||
// "*_options" sections don't require all defaults to be set
|
||||
if (
|
||||
$section !== 'model_options' &&
|
||||
($from = strlen($section) - strlen($opts)) >= 0 &&
|
||||
strpos($section, $opts, $from) !== false
|
||||
) {
|
||||
if (is_int(current($values))) {
|
||||
$config[$section] = array_map('intval', $config[$section]);
|
||||
}
|
||||
$this->_configuration[$section] = $config[$section];
|
||||
}
|
||||
// check for missing keys and set defaults if necessary
|
||||
else {
|
||||
foreach ($values as $key => $val) {
|
||||
if ($key == 'dir') {
|
||||
$val = PATH . $val;
|
||||
}
|
||||
$result = $val;
|
||||
if (array_key_exists($key, $config[$section])) {
|
||||
if ($val === null) {
|
||||
$result = $config[$section][$key];
|
||||
} elseif (is_bool($val)) {
|
||||
$val = strtolower($config[$section][$key]);
|
||||
if (in_array($val, array('true', 'yes', 'on'))) {
|
||||
$result = true;
|
||||
} elseif (in_array($val, array('false', 'no', 'off'))) {
|
||||
$result = false;
|
||||
} else {
|
||||
$result = (bool) $config[$section][$key];
|
||||
}
|
||||
} elseif (is_int($val)) {
|
||||
$result = (int) $config[$section][$key];
|
||||
} elseif (is_string($val) && !empty($config[$section][$key])) {
|
||||
$result = (string) $config[$section][$key];
|
||||
}
|
||||
}
|
||||
$this->_configuration[$section][$key] = $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// support for old config file format, before the fork was renamed and PSR-4 introduced
|
||||
$this->_configuration['model']['class'] = str_replace(
|
||||
'zerobin_', 'privatebin_',
|
||||
$this->_configuration['model']['class']
|
||||
);
|
||||
|
||||
$this->_configuration['model']['class'] = str_replace(
|
||||
array('privatebin_data', 'privatebin_db'),
|
||||
array('Filesystem', 'Database'),
|
||||
$this->_configuration['model']['class']
|
||||
);
|
||||
|
||||
// ensure a valid expire default key is set
|
||||
if (!array_key_exists($this->_configuration['expire']['default'], $this->_configuration['expire_options'])) {
|
||||
$this->_configuration['expire']['default'] = key($this->_configuration['expire_options']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get configuration as array
|
||||
*
|
||||
* return array
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return $this->_configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* get default configuration as array
|
||||
*
|
||||
* return array
|
||||
*/
|
||||
public static function getDefaults()
|
||||
{
|
||||
return self::$_defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a key from the configuration, typically the main section or all keys
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $section defaults to main
|
||||
* @throws Exception
|
||||
* return mixed
|
||||
*/
|
||||
public function getKey($key, $section = 'main')
|
||||
{
|
||||
$options = $this->getSection($section);
|
||||
if (!array_key_exists($key, $options)) {
|
||||
throw new Exception(I18n::_('Invalid data.') . " $section / $key", 4);
|
||||
}
|
||||
return $this->_configuration[$section][$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* get a section from the configuration, must exist
|
||||
*
|
||||
* @param string $section
|
||||
* @throws Exception
|
||||
* return mixed
|
||||
*/
|
||||
public function getSection($section)
|
||||
{
|
||||
if (!array_key_exists($section, $this->_configuration)) {
|
||||
throw new Exception(I18n::_('%s requires configuration section [%s] to be present in configuration file.', I18n::_($this->getKey('name')), $section), 3);
|
||||
}
|
||||
return $this->_configuration[$section];
|
||||
}
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* 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
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Data;
|
||||
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* AbstractData
|
||||
*
|
||||
* Abstract model for PrivateBin data access, implemented as a singleton.
|
||||
*/
|
||||
abstract class AbstractData
|
||||
{
|
||||
/**
|
||||
* singleton instance
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @var AbstractData
|
||||
*/
|
||||
protected static $_instance = null;
|
||||
|
||||
/**
|
||||
* enforce singleton, disable constructor
|
||||
*
|
||||
* Instantiate using {@link getInstance()}, privatebin is a singleton object.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* enforce singleton, disable cloning
|
||||
*
|
||||
* Instantiate using {@link getInstance()}, privatebin is a singleton object.
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* get instance of singleton
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param array $options
|
||||
* @return privatebin_abstract
|
||||
*/
|
||||
public static function getInstance($options)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @param array $paste
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function create($pasteid, $paste);
|
||||
|
||||
/**
|
||||
* Read a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return stdClass|false
|
||||
*/
|
||||
abstract public function read($pasteid);
|
||||
|
||||
/**
|
||||
* Delete a paste and its discussion.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return void
|
||||
*/
|
||||
abstract public function delete($pasteid);
|
||||
|
||||
/**
|
||||
* Test if a paste exists.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function exists($pasteid);
|
||||
|
||||
/**
|
||||
* Create a comment in a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @param string $parentid
|
||||
* @param string $commentid
|
||||
* @param array $comment
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function createComment($pasteid, $parentid, $commentid, $comment);
|
||||
|
||||
/**
|
||||
* Read all comments of paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return array
|
||||
*/
|
||||
abstract public function readComments($pasteid);
|
||||
|
||||
/**
|
||||
* Test if a comment exists.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @param string $parentid
|
||||
* @param string $commentid
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function existsComment($pasteid, $parentid, $commentid);
|
||||
|
||||
/**
|
||||
* Returns up to batch size number of paste ids that have expired
|
||||
*
|
||||
* @access protected
|
||||
* @param int $batchsize
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function _getExpiredPastes($batchsize);
|
||||
|
||||
/**
|
||||
* Perform a purge of old pastes, at most the given batchsize is deleted.
|
||||
*
|
||||
* @access public
|
||||
* @param int $batchsize
|
||||
* @return void
|
||||
*/
|
||||
public function purge($batchsize)
|
||||
{
|
||||
if ($batchsize < 1) {
|
||||
return;
|
||||
}
|
||||
$pastes = $this->_getExpiredPastes($batchsize);
|
||||
if (count($pastes)) {
|
||||
foreach ($pastes as $pasteid) {
|
||||
$this->delete($pasteid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next free slot for comment from postdate.
|
||||
*
|
||||
* @access public
|
||||
* @param array $comments
|
||||
* @param int|string $postdate
|
||||
* @return int|string
|
||||
*/
|
||||
protected function getOpenSlot(&$comments, $postdate)
|
||||
{
|
||||
if (array_key_exists($postdate, $comments)) {
|
||||
$parts = explode('.', $postdate, 2);
|
||||
if (!array_key_exists(1, $parts)) {
|
||||
$parts[1] = 0;
|
||||
}
|
||||
++$parts[1];
|
||||
return $this->getOpenSlot($comments, implode('.', $parts));
|
||||
}
|
||||
return $postdate;
|
||||
}
|
||||
}
|
@ -1,712 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* 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
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Data;
|
||||
|
||||
use Exception;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use PrivateBin\PrivateBin;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Database
|
||||
*
|
||||
* Model for database access, implemented as a singleton.
|
||||
*/
|
||||
class Database extends AbstractData
|
||||
{
|
||||
/**
|
||||
* cache for select queries
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $_cache = array();
|
||||
|
||||
/**
|
||||
* instance of database connection
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var PDO
|
||||
*/
|
||||
private static $_db;
|
||||
|
||||
/**
|
||||
* table prefix
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var string
|
||||
*/
|
||||
private static $_prefix = '';
|
||||
|
||||
/**
|
||||
* database type
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var string
|
||||
*/
|
||||
private static $_type = '';
|
||||
|
||||
/**
|
||||
* get instance of singleton
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param array $options
|
||||
* @throws Exception
|
||||
* @return Database
|
||||
*/
|
||||
public static function getInstance($options = null)
|
||||
{
|
||||
// if needed initialize the singleton
|
||||
if (!(self::$_instance instanceof self)) {
|
||||
self::$_instance = new self;
|
||||
}
|
||||
|
||||
if (is_array($options)) {
|
||||
// set table prefix if given
|
||||
if (array_key_exists('tbl', $options)) {
|
||||
self::$_prefix = $options['tbl'];
|
||||
}
|
||||
|
||||
// initialize the db connection with new options
|
||||
if (
|
||||
array_key_exists('dsn', $options) &&
|
||||
array_key_exists('usr', $options) &&
|
||||
array_key_exists('pwd', $options) &&
|
||||
array_key_exists('opt', $options)
|
||||
) {
|
||||
// set default options
|
||||
$options['opt'][PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
|
||||
$options['opt'][PDO::ATTR_EMULATE_PREPARES] = false;
|
||||
$options['opt'][PDO::ATTR_PERSISTENT] = true;
|
||||
$db_tables_exist = true;
|
||||
|
||||
// setup type and dabase connection
|
||||
self::$_type = strtolower(
|
||||
substr($options['dsn'], 0, strpos($options['dsn'], ':'))
|
||||
);
|
||||
$tableQuery = self::_getTableQuery(self::$_type);
|
||||
self::$_db = new PDO(
|
||||
$options['dsn'],
|
||||
$options['usr'],
|
||||
$options['pwd'],
|
||||
$options['opt']
|
||||
);
|
||||
|
||||
// check if the database contains the required tables
|
||||
$tables = self::$_db->query($tableQuery)->fetchAll(PDO::FETCH_COLUMN, 0);
|
||||
|
||||
// create paste table if necessary
|
||||
if (!in_array(self::_sanitizeIdentifier('paste'), $tables)) {
|
||||
self::_createPasteTable();
|
||||
$db_tables_exist = false;
|
||||
}
|
||||
|
||||
// create comment table if necessary
|
||||
if (!in_array(self::_sanitizeIdentifier('comment'), $tables)) {
|
||||
self::_createCommentTable();
|
||||
$db_tables_exist = false;
|
||||
}
|
||||
|
||||
// create config table if necessary
|
||||
$db_version = PrivateBin::VERSION;
|
||||
if (!in_array(self::_sanitizeIdentifier('config'), $tables)) {
|
||||
self::_createConfigTable();
|
||||
// if we only needed to create the config table, the DB is older then 0.22
|
||||
if ($db_tables_exist) {
|
||||
$db_version = '0.21';
|
||||
}
|
||||
} else {
|
||||
$db_version = self::_getConfig('VERSION');
|
||||
}
|
||||
|
||||
// update database structure if necessary
|
||||
if (version_compare($db_version, PrivateBin::VERSION, '<')) {
|
||||
self::_upgradeDatabase($db_version);
|
||||
}
|
||||
} else {
|
||||
throw new Exception(
|
||||
'Missing configuration for key dsn, usr, pwd or opt in the section model_options, please check your configuration file', 6
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @param array $paste
|
||||
* @return bool
|
||||
*/
|
||||
public function create($pasteid, $paste)
|
||||
{
|
||||
if (
|
||||
array_key_exists($pasteid, self::$_cache)
|
||||
) {
|
||||
if (false !== self::$_cache[$pasteid]) {
|
||||
return false;
|
||||
} else {
|
||||
unset(self::$_cache[$pasteid]);
|
||||
}
|
||||
}
|
||||
|
||||
$opendiscussion = $burnafterreading = false;
|
||||
$attachment = $attachmentname = '';
|
||||
$meta = $paste['meta'];
|
||||
unset($meta['postdate']);
|
||||
$expire_date = 0;
|
||||
if (array_key_exists('expire_date', $paste['meta'])) {
|
||||
$expire_date = (int) $paste['meta']['expire_date'];
|
||||
unset($meta['expire_date']);
|
||||
}
|
||||
if (array_key_exists('opendiscussion', $paste['meta'])) {
|
||||
$opendiscussion = (bool) $paste['meta']['opendiscussion'];
|
||||
unset($meta['opendiscussion']);
|
||||
}
|
||||
if (array_key_exists('burnafterreading', $paste['meta'])) {
|
||||
$burnafterreading = (bool) $paste['meta']['burnafterreading'];
|
||||
unset($meta['burnafterreading']);
|
||||
}
|
||||
if (array_key_exists('attachment', $paste['meta'])) {
|
||||
$attachment = $paste['meta']['attachment'];
|
||||
unset($meta['attachment']);
|
||||
}
|
||||
if (array_key_exists('attachmentname', $paste['meta'])) {
|
||||
$attachmentname = $paste['meta']['attachmentname'];
|
||||
unset($meta['attachmentname']);
|
||||
}
|
||||
return self::_exec(
|
||||
'INSERT INTO ' . self::_sanitizeIdentifier('paste') .
|
||||
' VALUES(?,?,?,?,?,?,?,?,?)',
|
||||
array(
|
||||
$pasteid,
|
||||
$paste['data'],
|
||||
$paste['meta']['postdate'],
|
||||
$expire_date,
|
||||
(int) $opendiscussion,
|
||||
(int) $burnafterreading,
|
||||
json_encode($meta),
|
||||
$attachment,
|
||||
$attachmentname,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return stdClass|false
|
||||
*/
|
||||
public function read($pasteid)
|
||||
{
|
||||
if (
|
||||
!array_key_exists($pasteid, self::$_cache)
|
||||
) {
|
||||
self::$_cache[$pasteid] = false;
|
||||
$paste = self::_select(
|
||||
'SELECT * FROM ' . self::_sanitizeIdentifier('paste') .
|
||||
' WHERE dataid = ?', array($pasteid), true
|
||||
);
|
||||
|
||||
if (false !== $paste) {
|
||||
// create object
|
||||
self::$_cache[$pasteid] = new stdClass;
|
||||
self::$_cache[$pasteid]->data = $paste['data'];
|
||||
|
||||
$meta = json_decode($paste['meta']);
|
||||
if (!is_object($meta)) {
|
||||
$meta = new stdClass;
|
||||
}
|
||||
|
||||
// support older attachments
|
||||
if (property_exists($meta, 'attachment')) {
|
||||
self::$_cache[$pasteid]->attachment = $meta->attachment;
|
||||
unset($meta->attachment);
|
||||
if (property_exists($meta, 'attachmentname')) {
|
||||
self::$_cache[$pasteid]->attachmentname = $meta->attachmentname;
|
||||
unset($meta->attachmentname);
|
||||
}
|
||||
}
|
||||
// support current attachments
|
||||
elseif (array_key_exists('attachment', $paste) && strlen($paste['attachment'])) {
|
||||
self::$_cache[$pasteid]->attachment = $paste['attachment'];
|
||||
if (array_key_exists('attachmentname', $paste) && strlen($paste['attachmentname'])) {
|
||||
self::$_cache[$pasteid]->attachmentname = $paste['attachmentname'];
|
||||
}
|
||||
}
|
||||
self::$_cache[$pasteid]->meta = $meta;
|
||||
self::$_cache[$pasteid]->meta->postdate = (int) $paste['postdate'];
|
||||
$expire_date = (int) $paste['expiredate'];
|
||||
if (
|
||||
$expire_date > 0
|
||||
) {
|
||||
self::$_cache[$pasteid]->meta->expire_date = $expire_date;
|
||||
}
|
||||
if (
|
||||
$paste['opendiscussion']
|
||||
) {
|
||||
self::$_cache[$pasteid]->meta->opendiscussion = true;
|
||||
}
|
||||
if (
|
||||
$paste['burnafterreading']
|
||||
) {
|
||||
self::$_cache[$pasteid]->meta->burnafterreading = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::$_cache[$pasteid];
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a paste and its discussion.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return void
|
||||
*/
|
||||
public function delete($pasteid)
|
||||
{
|
||||
self::_exec(
|
||||
'DELETE FROM ' . self::_sanitizeIdentifier('paste') .
|
||||
' WHERE dataid = ?', array($pasteid)
|
||||
);
|
||||
self::_exec(
|
||||
'DELETE FROM ' . self::_sanitizeIdentifier('comment') .
|
||||
' WHERE pasteid = ?', array($pasteid)
|
||||
);
|
||||
if (
|
||||
array_key_exists($pasteid, self::$_cache)
|
||||
) {
|
||||
unset(self::$_cache[$pasteid]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a paste exists.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($pasteid)
|
||||
{
|
||||
if (
|
||||
!array_key_exists($pasteid, self::$_cache)
|
||||
) {
|
||||
self::$_cache[$pasteid] = $this->read($pasteid);
|
||||
}
|
||||
return (bool) self::$_cache[$pasteid];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a comment in a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @param string $parentid
|
||||
* @param string $commentid
|
||||
* @param array $comment
|
||||
* @return bool
|
||||
*/
|
||||
public function createComment($pasteid, $parentid, $commentid, $comment)
|
||||
{
|
||||
foreach (array('nickname', 'vizhash') as $key) {
|
||||
if (!array_key_exists($key, $comment['meta'])) {
|
||||
$comment['meta'][$key] = null;
|
||||
}
|
||||
}
|
||||
return self::_exec(
|
||||
'INSERT INTO ' . self::_sanitizeIdentifier('comment') .
|
||||
' VALUES(?,?,?,?,?,?,?)',
|
||||
array(
|
||||
$commentid,
|
||||
$pasteid,
|
||||
$parentid,
|
||||
$comment['data'],
|
||||
$comment['meta']['nickname'],
|
||||
$comment['meta']['vizhash'],
|
||||
$comment['meta']['postdate'],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all comments of paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return array
|
||||
*/
|
||||
public function readComments($pasteid)
|
||||
{
|
||||
$rows = self::_select(
|
||||
'SELECT * FROM ' . self::_sanitizeIdentifier('comment') .
|
||||
' WHERE pasteid = ?', array($pasteid)
|
||||
);
|
||||
|
||||
// create comment list
|
||||
$comments = array();
|
||||
if (count($rows)) {
|
||||
foreach ($rows as $row) {
|
||||
$i = $this->getOpenSlot($comments, (int) $row['postdate']);
|
||||
$comments[$i] = new stdClass;
|
||||
$comments[$i]->id = $row['dataid'];
|
||||
$comments[$i]->parentid = $row['parentid'];
|
||||
$comments[$i]->data = $row['data'];
|
||||
$comments[$i]->meta = new stdClass;
|
||||
$comments[$i]->meta->postdate = (int) $row['postdate'];
|
||||
if (array_key_exists('nickname', $row) && !empty($row['nickname'])) {
|
||||
$comments[$i]->meta->nickname = $row['nickname'];
|
||||
}
|
||||
if (array_key_exists('vizhash', $row) && !empty($row['vizhash'])) {
|
||||
$comments[$i]->meta->vizhash = $row['vizhash'];
|
||||
}
|
||||
}
|
||||
ksort($comments);
|
||||
}
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a comment exists.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @param string $parentid
|
||||
* @param string $commentid
|
||||
* @return bool
|
||||
*/
|
||||
public function existsComment($pasteid, $parentid, $commentid)
|
||||
{
|
||||
return (bool) self::_select(
|
||||
'SELECT dataid FROM ' . self::_sanitizeIdentifier('comment') .
|
||||
' WHERE pasteid = ? AND parentid = ? AND dataid = ?',
|
||||
array($pasteid, $parentid, $commentid), true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns up to batch size number of paste ids that have expired
|
||||
*
|
||||
* @access private
|
||||
* @param int $batchsize
|
||||
* @return array
|
||||
*/
|
||||
protected function _getExpiredPastes($batchsize)
|
||||
{
|
||||
$pastes = array();
|
||||
$rows = self::_select(
|
||||
'SELECT dataid FROM ' . self::_sanitizeIdentifier('paste') .
|
||||
' WHERE expiredate < ? AND expiredate != ? LIMIT ?', array(time(), 0, $batchsize)
|
||||
);
|
||||
if (count($rows)) {
|
||||
foreach ($rows as $row) {
|
||||
$pastes[] = $row['dataid'];
|
||||
}
|
||||
}
|
||||
return $pastes;
|
||||
}
|
||||
|
||||
/**
|
||||
* execute a statement
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $sql
|
||||
* @param array $params
|
||||
* @throws PDOException
|
||||
* @return bool
|
||||
*/
|
||||
private static function _exec($sql, array $params)
|
||||
{
|
||||
$statement = self::$_db->prepare($sql);
|
||||
$result = $statement->execute($params);
|
||||
$statement->closeCursor();
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* run a select statement
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $sql
|
||||
* @param array $params
|
||||
* @param bool $firstOnly if only the first row should be returned
|
||||
* @throws PDOException
|
||||
* @return array
|
||||
*/
|
||||
private static function _select($sql, array $params, $firstOnly = false)
|
||||
{
|
||||
$statement = self::$_db->prepare($sql);
|
||||
$statement->execute($params);
|
||||
$result = $firstOnly ?
|
||||
$statement->fetch(PDO::FETCH_ASSOC) :
|
||||
$statement->fetchAll(PDO::FETCH_ASSOC);
|
||||
$statement->closeCursor();
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* get table list query, depending on the database type
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $type
|
||||
* @throws Exception
|
||||
* @return string
|
||||
*/
|
||||
private static function _getTableQuery($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'ibm':
|
||||
$sql = 'SELECT tabname FROM SYSCAT.TABLES ';
|
||||
break;
|
||||
case 'informix':
|
||||
$sql = 'SELECT tabname FROM systables ';
|
||||
break;
|
||||
case 'mssql':
|
||||
$sql = 'SELECT name FROM sysobjects '
|
||||
. "WHERE type = 'U' ORDER BY name";
|
||||
break;
|
||||
case 'mysql':
|
||||
$sql = 'SHOW TABLES';
|
||||
break;
|
||||
case 'oci':
|
||||
$sql = 'SELECT table_name FROM all_tables';
|
||||
break;
|
||||
case 'pgsql':
|
||||
$sql = 'SELECT c.relname AS table_name '
|
||||
. 'FROM pg_class c, pg_user u '
|
||||
. "WHERE c.relowner = u.usesysid AND c.relkind = 'r' "
|
||||
. 'AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname) '
|
||||
. "AND c.relname !~ '^(pg_|sql_)' "
|
||||
. 'UNION '
|
||||
. 'SELECT c.relname AS table_name '
|
||||
. 'FROM pg_class c '
|
||||
. "WHERE c.relkind = 'r' "
|
||||
. 'AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname) '
|
||||
. 'AND NOT EXISTS (SELECT 1 FROM pg_user WHERE usesysid = c.relowner) '
|
||||
. "AND c.relname !~ '^pg_'";
|
||||
break;
|
||||
case 'sqlite':
|
||||
$sql = "SELECT name FROM sqlite_master WHERE type='table' "
|
||||
. 'UNION ALL SELECT name FROM sqlite_temp_master '
|
||||
. "WHERE type='table' ORDER BY name";
|
||||
break;
|
||||
default:
|
||||
throw new Exception(
|
||||
"PDO type $type is currently not supported.", 5
|
||||
);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a value by key from the config table
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $key
|
||||
* @throws PDOException
|
||||
* @return string
|
||||
*/
|
||||
private static function _getConfig($key)
|
||||
{
|
||||
$row = self::_select(
|
||||
'SELECT value FROM ' . self::_sanitizeIdentifier('config') .
|
||||
' WHERE id = ?', array($key), true
|
||||
);
|
||||
return $row['value'];
|
||||
}
|
||||
|
||||
/**
|
||||
* get the primary key clauses, depending on the database driver
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
private static function _getPrimaryKeyClauses($key = 'dataid')
|
||||
{
|
||||
$main_key = $after_key = '';
|
||||
if (self::$_type === 'mysql') {
|
||||
$after_key = ", PRIMARY KEY ($key)";
|
||||
} else {
|
||||
$main_key = ' PRIMARY KEY';
|
||||
}
|
||||
return array($main_key, $after_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* create the paste table
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
private static function _createPasteTable()
|
||||
{
|
||||
list($main_key, $after_key) = self::_getPrimaryKeyClauses();
|
||||
$dataType = self::$_type === 'pgsql' ? 'TEXT' : 'BLOB';
|
||||
self::$_db->exec(
|
||||
'CREATE TABLE ' . self::_sanitizeIdentifier('paste') . ' ( ' .
|
||||
"dataid CHAR(16) NOT NULL$main_key, " .
|
||||
"data $dataType, " .
|
||||
'postdate INT, ' .
|
||||
'expiredate INT, ' .
|
||||
'opendiscussion INT, ' .
|
||||
'burnafterreading INT, ' .
|
||||
'meta TEXT, ' .
|
||||
'attachment ' . (self::$_type === 'pgsql' ? 'TEXT' : 'MEDIUMBLOB') . ', ' .
|
||||
"attachmentname $dataType$after_key );"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* create the paste table
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
private static function _createCommentTable()
|
||||
{
|
||||
list($main_key, $after_key) = self::_getPrimaryKeyClauses();
|
||||
$dataType = self::$_type === 'pgsql' ? 'text' : 'BLOB';
|
||||
self::$_db->exec(
|
||||
'CREATE TABLE ' . self::_sanitizeIdentifier('comment') . ' ( ' .
|
||||
"dataid CHAR(16) NOT NULL$main_key, " .
|
||||
'pasteid CHAR(16), ' .
|
||||
'parentid CHAR(16), ' .
|
||||
"data $dataType, " .
|
||||
"nickname $dataType, " .
|
||||
"vizhash $dataType, " .
|
||||
"postdate INT$after_key );"
|
||||
);
|
||||
self::$_db->exec(
|
||||
'CREATE INDEX IF NOT EXISTS comment_parent ON ' .
|
||||
self::_sanitizeIdentifier('comment') . '(pasteid);'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* create the paste table
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
private static function _createConfigTable()
|
||||
{
|
||||
list($main_key, $after_key) = self::_getPrimaryKeyClauses('id');
|
||||
self::$_db->exec(
|
||||
'CREATE TABLE ' . self::_sanitizeIdentifier('config') .
|
||||
" ( id CHAR(16) NOT NULL$main_key, value TEXT$after_key );"
|
||||
);
|
||||
self::_exec(
|
||||
'INSERT INTO ' . self::_sanitizeIdentifier('config') .
|
||||
' VALUES(?,?)',
|
||||
array('VERSION', PrivateBin::VERSION)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* sanitizes identifiers
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $identifier
|
||||
* @return string
|
||||
*/
|
||||
private static function _sanitizeIdentifier($identifier)
|
||||
{
|
||||
return preg_replace('/[^A-Za-z0-9_]+/', '', self::$_prefix . $identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* upgrade the database schema from an old version
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $oldversion
|
||||
* @return void
|
||||
*/
|
||||
private static function _upgradeDatabase($oldversion)
|
||||
{
|
||||
$dataType = self::$_type === 'pgsql' ? 'TEXT' : 'BLOB';
|
||||
switch ($oldversion) {
|
||||
case '0.21':
|
||||
// create the meta column if necessary (pre 0.21 change)
|
||||
try {
|
||||
self::$_db->exec('SELECT meta FROM ' . self::_sanitizeIdentifier('paste') . ' LIMIT 1;');
|
||||
} catch (PDOException $e) {
|
||||
self::$_db->exec('ALTER TABLE ' . self::_sanitizeIdentifier('paste') . ' ADD COLUMN meta TEXT;');
|
||||
}
|
||||
// SQLite only allows one ALTER statement at a time...
|
||||
self::$_db->exec(
|
||||
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') .
|
||||
' ADD COLUMN attachment ' .
|
||||
(self::$_type === 'pgsql' ? 'TEXT' : 'MEDIUMBLOB') . ';'
|
||||
);
|
||||
self::$_db->exec(
|
||||
'ALTER TABLE ' . self::_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 (self::$_type !== 'sqlite') {
|
||||
self::$_db->exec(
|
||||
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') .
|
||||
' ADD PRIMARY KEY (dataid), MODIFY COLUMN data $dataType;'
|
||||
);
|
||||
self::$_db->exec(
|
||||
'ALTER TABLE ' . self::_sanitizeIdentifier('comment') .
|
||||
" ADD PRIMARY KEY (dataid), MODIFY COLUMN data $dataType, " .
|
||||
"MODIFY COLUMN nickname $dataType, MODIFY COLUMN vizhash $dataType;"
|
||||
);
|
||||
} else {
|
||||
self::$_db->exec(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS paste_dataid ON ' .
|
||||
self::_sanitizeIdentifier('paste') . '(dataid);'
|
||||
);
|
||||
self::$_db->exec(
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS comment_dataid ON ' .
|
||||
self::_sanitizeIdentifier('comment') . '(dataid);'
|
||||
);
|
||||
}
|
||||
self::$_db->exec(
|
||||
'CREATE INDEX IF NOT EXISTS comment_parent ON ' .
|
||||
self::_sanitizeIdentifier('comment') . '(pasteid);'
|
||||
);
|
||||
// no break, continue with updates for 0.22
|
||||
case '0.22':
|
||||
case '1.0':
|
||||
self::_exec(
|
||||
'UPDATE ' . self::_sanitizeIdentifier('config') .
|
||||
' SET value = ? WHERE id = ?',
|
||||
array(PrivateBin::VERSION, 'VERSION')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,381 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* 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
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
namespace PrivateBin\Data;
|
||||
|
||||
use PrivateBin\Json;
|
||||
use PrivateBin\Model\Paste;
|
||||
|
||||
/**
|
||||
* Filesystem
|
||||
*
|
||||
* Model for filesystem data access, implemented as a singleton.
|
||||
*/
|
||||
class Filesystem extends AbstractData
|
||||
{
|
||||
/**
|
||||
* directory where data is stored
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var string
|
||||
*/
|
||||
private static $_dir = 'data/';
|
||||
|
||||
/**
|
||||
* get instance of singleton
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param array $options
|
||||
* @return Filesystem
|
||||
*/
|
||||
public static function getInstance($options = null)
|
||||
{
|
||||
// if given update the data directory
|
||||
if (
|
||||
is_array($options) &&
|
||||
array_key_exists('dir', $options)
|
||||
) {
|
||||
self::$_dir = $options['dir'] . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
// if needed initialize the singleton
|
||||
if (!(self::$_instance instanceof self)) {
|
||||
self::$_instance = new self;
|
||||
self::_init();
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @param array $paste
|
||||
* @throws Exception
|
||||
* @return bool
|
||||
*/
|
||||
public function create($pasteid, $paste)
|
||||
{
|
||||
$storagedir = self::_dataid2path($pasteid);
|
||||
if (is_file($storagedir . $pasteid)) {
|
||||
return false;
|
||||
}
|
||||
if (!is_dir($storagedir)) {
|
||||
mkdir($storagedir, 0700, true);
|
||||
}
|
||||
return (bool) file_put_contents($storagedir . $pasteid, Json::encode($paste));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return stdClass|false
|
||||
*/
|
||||
public function read($pasteid)
|
||||
{
|
||||
if (!$this->exists($pasteid)) {
|
||||
return false;
|
||||
}
|
||||
$paste = json_decode(
|
||||
file_get_contents(self::_dataid2path($pasteid) . $pasteid)
|
||||
);
|
||||
if (property_exists($paste->meta, 'attachment')) {
|
||||
$paste->attachment = $paste->meta->attachment;
|
||||
unset($paste->meta->attachment);
|
||||
if (property_exists($paste->meta, 'attachmentname')) {
|
||||
$paste->attachmentname = $paste->meta->attachmentname;
|
||||
unset($paste->meta->attachmentname);
|
||||
}
|
||||
}
|
||||
return $paste;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a paste and its discussion.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return void
|
||||
*/
|
||||
public function delete($pasteid)
|
||||
{
|
||||
$pastedir = self::_dataid2path($pasteid);
|
||||
if (is_dir($pastedir)) {
|
||||
// Delete the paste itself.
|
||||
if (is_file($pastedir . $pasteid)) {
|
||||
unlink($pastedir . $pasteid);
|
||||
}
|
||||
|
||||
// Delete discussion if it exists.
|
||||
$discdir = self::_dataid2discussionpath($pasteid);
|
||||
if (is_dir($discdir)) {
|
||||
// Delete all files in discussion directory
|
||||
$dir = dir($discdir);
|
||||
while (false !== ($filename = $dir->read())) {
|
||||
if (is_file($discdir . $filename)) {
|
||||
unlink($discdir . $filename);
|
||||
}
|
||||
}
|
||||
$dir->close();
|
||||
rmdir($discdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a paste exists.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($pasteid)
|
||||
{
|
||||
return is_file(self::_dataid2path($pasteid) . $pasteid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a comment in a paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @param string $parentid
|
||||
* @param string $commentid
|
||||
* @param array $comment
|
||||
* @throws Exception
|
||||
* @return bool
|
||||
*/
|
||||
public function createComment($pasteid, $parentid, $commentid, $comment)
|
||||
{
|
||||
$storagedir = self::_dataid2discussionpath($pasteid);
|
||||
$filename = $pasteid . '.' . $commentid . '.' . $parentid;
|
||||
if (is_file($storagedir . $filename)) {
|
||||
return false;
|
||||
}
|
||||
if (!is_dir($storagedir)) {
|
||||
mkdir($storagedir, 0700, true);
|
||||
}
|
||||
return (bool) file_put_contents($storagedir . $filename, Json::encode($comment));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all comments of paste.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return array
|
||||
*/
|
||||
public function readComments($pasteid)
|
||||
{
|
||||
$comments = array();
|
||||
$discdir = self::_dataid2discussionpath($pasteid);
|
||||
if (is_dir($discdir)) {
|
||||
// Delete all files in discussion directory
|
||||
$dir = dir($discdir);
|
||||
while (false !== ($filename = $dir->read())) {
|
||||
// Filename is in the form pasteid.commentid.parentid:
|
||||
// - pasteid is the paste this reply belongs to.
|
||||
// - commentid is the comment identifier itself.
|
||||
// - parentid is the comment this comment replies to (It can be pasteid)
|
||||
if (is_file($discdir . $filename)) {
|
||||
$comment = json_decode(file_get_contents($discdir . $filename));
|
||||
$items = explode('.', $filename);
|
||||
// Add some meta information not contained in file.
|
||||
$comment->id = $items[1];
|
||||
$comment->parentid = $items[2];
|
||||
|
||||
// Store in array
|
||||
$key = $this->getOpenSlot($comments, (int) $comment->meta->postdate);
|
||||
$comments[$key] = $comment;
|
||||
}
|
||||
}
|
||||
$dir->close();
|
||||
|
||||
// Sort comments by date, oldest first.
|
||||
ksort($comments);
|
||||
}
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a comment exists.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @param string $parentid
|
||||
* @param string $commentid
|
||||
* @return bool
|
||||
*/
|
||||
public function existsComment($pasteid, $parentid, $commentid)
|
||||
{
|
||||
return is_file(
|
||||
self::_dataid2discussionpath($pasteid) .
|
||||
$pasteid . '.' . $commentid . '.' . $parentid
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns up to batch size number of paste ids that have expired
|
||||
*
|
||||
* @access private
|
||||
* @param int $batchsize
|
||||
* @return array
|
||||
*/
|
||||
protected function _getExpiredPastes($batchsize)
|
||||
{
|
||||
$pastes = array();
|
||||
$firstLevel = array_filter(
|
||||
scandir(self::$_dir),
|
||||
'self::_isFirstLevelDir'
|
||||
);
|
||||
if (count($firstLevel) > 0) {
|
||||
// try at most 10 times the $batchsize pastes before giving up
|
||||
for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) {
|
||||
$firstKey = array_rand($firstLevel);
|
||||
$secondLevel = array_filter(
|
||||
scandir(self::$_dir . $firstLevel[$firstKey]),
|
||||
'self::_isSecondLevelDir'
|
||||
);
|
||||
|
||||
// skip this folder in the next checks if it is empty
|
||||
if (count($secondLevel) == 0) {
|
||||
unset($firstLevel[$firstKey]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$secondKey = array_rand($secondLevel);
|
||||
$path = self::$_dir . $firstLevel[$firstKey] .
|
||||
DIRECTORY_SEPARATOR . $secondLevel[$secondKey];
|
||||
if (!is_dir($path)) {
|
||||
continue;
|
||||
}
|
||||
$thirdLevel = array_filter(
|
||||
scandir($path),
|
||||
'PrivateBin\\Model\\Paste::isValidId'
|
||||
);
|
||||
if (count($thirdLevel) == 0) {
|
||||
continue;
|
||||
}
|
||||
$thirdKey = array_rand($thirdLevel);
|
||||
$pasteid = $thirdLevel[$thirdKey];
|
||||
if (in_array($pasteid, $pastes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->exists($pasteid)) {
|
||||
$data = $this->read($pasteid);
|
||||
if (
|
||||
property_exists($data->meta, 'expire_date') &&
|
||||
$data->meta->expire_date < time()
|
||||
) {
|
||||
$pastes[] = $pasteid;
|
||||
if (count($pastes) >= $batchsize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pastes;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize privatebin
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
private static function _init()
|
||||
{
|
||||
// Create storage directory if it does not exist.
|
||||
if (!is_dir(self::$_dir)) {
|
||||
mkdir(self::$_dir, 0700);
|
||||
}
|
||||
// Create .htaccess file if it does not exist.
|
||||
if (!is_file(self::$_dir . '.htaccess')) {
|
||||
file_put_contents(
|
||||
self::$_dir . '.htaccess',
|
||||
'Allow from none' . PHP_EOL .
|
||||
'Deny from all' . PHP_EOL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert paste id to storage path.
|
||||
*
|
||||
* The idea is to creates subdirectories in order to limit the number of files per directory.
|
||||
* (A high number of files in a single directory can slow things down.)
|
||||
* eg. "f468483c313401e8" will be stored in "data/f4/68/f468483c313401e8"
|
||||
* High-trafic websites may want to deepen the directory structure (like Squid does).
|
||||
*
|
||||
* eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/'
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $dataid
|
||||
* @return string
|
||||
*/
|
||||
private static function _dataid2path($dataid)
|
||||
{
|
||||
return self::$_dir . substr($dataid, 0, 2) . DIRECTORY_SEPARATOR .
|
||||
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert paste id to discussion storage path.
|
||||
*
|
||||
* eg. input 'e3570978f9e4aa90' --> output 'data/e3/57/e3570978f9e4aa90.discussion/'
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $dataid
|
||||
* @return string
|
||||
*/
|
||||
private static function _dataid2discussionpath($dataid)
|
||||
{
|
||||
return self::_dataid2path($dataid) . $dataid .
|
||||
'.discussion' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given element is a valid first level directory.
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $element
|
||||
* @return bool
|
||||
*/
|
||||
private static function _isFirstLevelDir($element)
|
||||
{
|
||||
return self::_isSecondLevelDir($element) &&
|
||||
is_dir(self::$_dir . DIRECTORY_SEPARATOR . $element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given element is a valid second level directory.
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @param string $element
|
||||
* @return bool
|
||||
*/
|
||||
private static function _isSecondLevelDir($element)
|
||||
{
|
||||
return (bool) preg_match('/^[a-f0-9]{2}$/', $element);
|
||||
}
|
||||
}
|