Merge branch 'master' into attachment-handling
# Conflicts: # js/privatebin.js # tpl/bootstrap.php # tpl/page.php
This commit is contained in:
commit
096f07f86e
18
.eslintrc
18
.eslintrc
|
@ -15,7 +15,9 @@ globals:
|
|||
# http://eslint.org/docs/rules/
|
||||
rules:
|
||||
# Possible Errors
|
||||
comma-dangle: [2, never]
|
||||
comma-dangle:
|
||||
- error
|
||||
- never
|
||||
no-cond-assign: 2
|
||||
no-console: 0
|
||||
no-constant-condition: 2
|
||||
|
@ -31,7 +33,9 @@ rules:
|
|||
no-extra-parens: 0
|
||||
no-extra-semi: 2
|
||||
no-func-assign: 2
|
||||
no-inner-declarations: [2, functions]
|
||||
no-inner-declarations:
|
||||
- error
|
||||
- functions
|
||||
no-invalid-regexp: 2
|
||||
no-irregular-whitespace: 2
|
||||
no-negated-in-lhs: 2
|
||||
|
@ -47,7 +51,9 @@ rules:
|
|||
# Best Practices
|
||||
accessor-pairs: 2
|
||||
block-scoped-var: 0
|
||||
complexity: [2, 6]
|
||||
complexity:
|
||||
- error
|
||||
- 20
|
||||
consistent-return: 0
|
||||
curly: 0
|
||||
default-case: 0
|
||||
|
@ -99,7 +105,7 @@ rules:
|
|||
no-with: 2
|
||||
radix: 2
|
||||
vars-on-top: 0
|
||||
wrap-iife: 2
|
||||
wrap-iife: 0
|
||||
yoda: 0
|
||||
|
||||
# Strict
|
||||
|
@ -152,7 +158,9 @@ rules:
|
|||
max-len: 0
|
||||
max-nested-callbacks: 0
|
||||
max-params: 0
|
||||
max-statements: [2, 30]
|
||||
max-statements:
|
||||
- error
|
||||
- 60
|
||||
new-cap: 0
|
||||
new-parens: 0
|
||||
newline-after-var: 0
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Ignore server files for safety
|
||||
.htaccess
|
||||
.htpasswd
|
||||
cfg/conf.ini
|
||||
|
||||
# Ignore data/
|
||||
data/
|
||||
|
@ -30,6 +31,7 @@ vendor/**/build_phar.php
|
|||
# Ignore local node modules, unit testing logs, api docs and eclipse project files
|
||||
js/node_modules/
|
||||
tst/log/
|
||||
tst/ConfigurationCombinationsTest.php
|
||||
.settings
|
||||
.buildpath
|
||||
.project
|
||||
|
|
19
.travis.yml
19
.travis.yml
|
@ -1,15 +1,26 @@
|
|||
language: php
|
||||
sudo: false
|
||||
php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- '5.4'
|
||||
- '5.5'
|
||||
- '5.6'
|
||||
- '7.0'
|
||||
- '7.1'
|
||||
|
||||
# as this is a php project, node.js v4 (for JS unit testing) isn't installed
|
||||
install:
|
||||
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install 4
|
||||
|
||||
before_script:
|
||||
- composer install -n
|
||||
- npm install -g mocha
|
||||
- cd js
|
||||
- npm install jsverify jsdom jsdom-global
|
||||
- cd ..
|
||||
|
||||
script:
|
||||
- cd tst && phpunit
|
||||
- cd tst && ../vendor/bin/phpunit
|
||||
- cd ../js && mocha
|
||||
|
||||
after_script:
|
||||
- cd ..
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
# PrivateBin version history
|
||||
|
||||
* **next (not yet released)**
|
||||
* ADDED: Translations for Spanish, Occitan and Norwegian
|
||||
* ADDED: Translations for Spanish, Occitan, Norwegian and Portuguese
|
||||
* ADDED: Option in configuration to change the default "PrivateBin" title of the site
|
||||
* CHANGED: Minimum required PHP version is 5.4 (#186)
|
||||
* CHANGED: Shipped .htaccess files were updated for Apache 2.4 (#192)
|
||||
* CHANGED: Cleanup of bootstrap template variants and moved icons to `img` directory
|
||||
* **1.1 (2016-12-26)**
|
||||
* ADDED: Translations for Italian and Russian
|
||||
|
|
|
@ -35,3 +35,4 @@ Sébastien Sauvage - original idea and main developer
|
|||
* Alfredo Fabián Altamirano Tena - Spanish
|
||||
* Quent-in - Occitan
|
||||
* idarlund - Norwegian
|
||||
* Tulio Leao - Portuguese
|
||||
|
|
|
@ -10,7 +10,7 @@ check the options and adjust them as you see fit.
|
|||
|
||||
### Requirements
|
||||
|
||||
- PHP version 5.3 or above
|
||||
- PHP version 5.4 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)
|
||||
|
|
|
@ -16,10 +16,10 @@ Data is encrypted/decrypted in the browser using 256bit AES in [Galois Counter m
|
|||
|
||||
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
|
||||
to allow easier and cleaner extensions and has now many 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.
|
||||
without losing any data.
|
||||
|
||||
## What PrivateBin provides
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/conf.ini
|
|
@ -1,2 +1 @@
|
|||
Allow from none
|
||||
Deny from all
|
||||
Require all denied
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^5.3.0 || ^7.0",
|
||||
"php": "^5.4.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"
|
||||
"codeclimate/php-test-reporter": "dev-master",
|
||||
"phpunit/phpunit": "^4.6 || ^5.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
|
@ -17,6 +17,10 @@ body.navbar-spacing {
|
|||
padding-top: 70px;
|
||||
}
|
||||
|
||||
body.loading {
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.buttondisabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
@ -115,6 +119,12 @@ body.navbar-spacing {
|
|||
border-left: 1px solid #ccc;
|
||||
padding: 5px 0 5px 10px;
|
||||
white-space: pre-wrap;
|
||||
transition: background-color 0.75s ease-out;
|
||||
}
|
||||
|
||||
.comment.highlight {
|
||||
background-color: #ffdd86;
|
||||
transition: background-color 0.2s ease-in;
|
||||
}
|
||||
|
||||
footer h4 {
|
||||
|
|
42
i18n/de.json
42
i18n/de.json
|
@ -7,8 +7,8 @@
|
|||
"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 php %s or above to work. Sorry.":
|
||||
"%s benötigt PHP %s 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.":
|
||||
|
@ -83,25 +83,25 @@
|
|||
"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.",
|
||||
"Konnte das Paste nicht löschen, es 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.",
|
||||
"DIESER TEXT IST NUR FÜR DICH GEDACHT. Schließe 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)",
|
||||
"Avatar generated from IP address":
|
||||
"Avatar (generiert aus der IP-Adresse)",
|
||||
"Add comment":
|
||||
"Kommentar hinzufügen",
|
||||
"Optional nickname...":
|
||||
"Optionales Pseudonym...",
|
||||
"Optional nickname…":
|
||||
"Optionales Pseudonym…",
|
||||
"Post comment":
|
||||
"Kommentar absenden",
|
||||
"Sending comment...":
|
||||
"Sende Kommentar...",
|
||||
"Sending comment…":
|
||||
"Sende Kommentar…",
|
||||
"Comment posted.":
|
||||
"Kommentar gesendet.",
|
||||
"Could not refresh display: %s":
|
||||
|
@ -112,24 +112,25 @@
|
|||
"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...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Bitte bewege Deine Maus um die Entropie zu erhöhen…",
|
||||
"Sending paste…":
|
||||
"Sende Paste…",
|
||||
"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>",
|
||||
"Dein Paste 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",
|
||||
"Konnte Paste 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?)",
|
||||
"Konnte Paste 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.",
|
||||
"Cloned: '%s'": "Geklont: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "Die geklonte Datei '%s' wurde angehängt.",
|
||||
"Attach a file": "Datei anhängen",
|
||||
"or drag & drop file": "oder per Drag & Drop einfügen",
|
||||
"File too large, to display a preview. Please download the attachment.": "Datei zu groß, um als Vorschau angezeigt zu werden. Bitte Anhang herunterladen.",
|
||||
|
@ -148,6 +149,9 @@
|
|||
"Enter password":
|
||||
"Passwort eingeben",
|
||||
"Loading…": "Lädt…",
|
||||
"Decrypting paste…": "Entschlüssle Paste…",
|
||||
"Preparing new paste…": "Bereite neues Paste vor…",
|
||||
"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."
|
||||
"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.",
|
||||
"+++ no paste text +++": "+++ kein Paste-Text +++"
|
||||
}
|
||||
|
|
32
i18n/es.json
32
i18n/es.json
|
@ -7,10 +7,10 @@
|
|||
"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 php %s or above to work. Sorry.":
|
||||
"%s requiere php %s 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.",
|
||||
"%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.":
|
||||
|
@ -92,16 +92,16 @@
|
|||
"Responder",
|
||||
"Anonymous":
|
||||
"Anónimo",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar generated from IP address":
|
||||
"Avatar anónimo (Vizhash de la dirección IP)",
|
||||
"Add comment":
|
||||
"Añadir comentario",
|
||||
"Optional nickname...":
|
||||
"Seudónimo opcional...",
|
||||
"Optional nickname…":
|
||||
"Seudónimo opcional…",
|
||||
"Post comment":
|
||||
"Publicar comentario",
|
||||
"Sending comment...":
|
||||
"Enviando comentario...",
|
||||
"Sending comment…":
|
||||
"Enviando comentario…",
|
||||
"Comment posted.":
|
||||
"Comentario publicado.",
|
||||
"Could not refresh display: %s":
|
||||
|
@ -112,10 +112,10 @@
|
|||
"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...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"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":
|
||||
|
@ -129,7 +129,8 @@
|
|||
"Source Code": "Código fuente",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Descargar adjunto",
|
||||
"Cloned file attached.": "Archivo clonado adjunto.",
|
||||
"Cloned: '%s'": "Clonado: '%s'.",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"Attach a file": "Adjuntar archivo",
|
||||
"Remove attachment": "Remover adjunto",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
|
@ -146,6 +147,9 @@
|
|||
"Enter password":
|
||||
"Ingrese contraseña",
|
||||
"Loading…": "Cargando…",
|
||||
"Decrypting paste…": "Decrypting paste…",
|
||||
"Preparing new paste…": "Preparing new paste…",
|
||||
"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>."
|
||||
"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>.",
|
||||
"+++ no paste text +++": "+++ no paste text +++"
|
||||
}
|
||||
|
|
36
i18n/fr.json
36
i18n/fr.json
|
@ -7,8 +7,8 @@
|
|||
"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 php %s or above to work. Sorry.":
|
||||
"Désolé, %s nécessite php %s 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.":
|
||||
|
@ -92,16 +92,16 @@
|
|||
"Répondre",
|
||||
"Anonymous":
|
||||
"Anonyme",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar generated from IP address":
|
||||
"Avatar anonyme (Vizhash de l'adresse IP)",
|
||||
"Add comment":
|
||||
"Ajouter un commentaire",
|
||||
"Optional nickname...":
|
||||
"Pseudonyme optionnel...",
|
||||
"Optional nickname…":
|
||||
"Pseudonyme optionnel…",
|
||||
"Post comment":
|
||||
"Poster le commentaire",
|
||||
"Sending comment...":
|
||||
"Envoi du commentaire...",
|
||||
"Sending comment…":
|
||||
"Envoi du commentaire…",
|
||||
"Comment posted.":
|
||||
"Commentaire posté.",
|
||||
"Could not refresh display: %s":
|
||||
|
@ -112,10 +112,10 @@
|
|||
"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...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"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":
|
||||
|
@ -138,7 +138,8 @@
|
|||
"Source Code": "Code source",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Télécharger la pièce jointe",
|
||||
"Cloned file attached.": "Cloner le fichier attaché.",
|
||||
"Cloned: '%s'": "Cloner '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"Attach a file": "Attacher un fichier ",
|
||||
"Remove attachment": "Enlever l'attachement",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
|
@ -149,12 +150,15 @@
|
|||
"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.",
|
||||
"%s requiert que le PATH se termine dans un \"%s\". Veuillez mettre à jour le PATH dans votre index.php.",
|
||||
"Decrypt":
|
||||
"Decrypt",
|
||||
"Déchiffrer",
|
||||
"Enter password":
|
||||
"Entrez le mot de passe",
|
||||
"Loading…": "Loading…",
|
||||
"Loading…": "Chargement…",
|
||||
"Decrypting paste…": "Decrypting paste…",
|
||||
"Preparing new paste…": "Preparing new paste…",
|
||||
"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)."
|
||||
"Si ce message ne disparaîssait pas, jetez un oeil à <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">cette FAQ pour des idées de résolution</a> (en Anglais).",
|
||||
"+++ no paste text +++": "+++ no paste text +++"
|
||||
}
|
||||
|
|
48
i18n/it.json
48
i18n/it.json
|
@ -7,8 +7,8 @@
|
|||
"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 php %s or above to work. Sorry.":
|
||||
"%s richiede php %s o superiore per funzionare. Ci spiace.",
|
||||
"%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.":
|
||||
|
@ -18,7 +18,7 @@
|
|||
"Invalid data.":
|
||||
"Dati non validi.",
|
||||
"You are unlucky. Try again.":
|
||||
"Riprova, sarai più fortunato.",
|
||||
"Ritenta, sarai più fortunato.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Errore durante il salvataggio del commento.",
|
||||
"Error saving paste. Sorry.":
|
||||
|
@ -67,7 +67,7 @@
|
|||
"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.",
|
||||
"Nota: questo è un servizio di prova, i messaggi salvati possono essere cancellati in qualsiasi momento. Moriranno dei gattini se abuserai di questo servizio.",
|
||||
"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.":
|
||||
|
@ -87,41 +87,41 @@
|
|||
"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?)",
|
||||
"Non riesco a decifrare il commento (Chiave errata?)",
|
||||
"Reply":
|
||||
"Rispondi",
|
||||
"Anonymous":
|
||||
"Anonimo",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar Anonino (Vizhash dell'indirizzo IP)",
|
||||
"Avatar generated from IP address":
|
||||
"Avatar generato dall'indirizzo IP)",
|
||||
"Add comment":
|
||||
"Aggiungi un commento",
|
||||
"Optional nickname...":
|
||||
"Nickname opzionale...",
|
||||
"Optional nickname…":
|
||||
"Nickname opzionale…",
|
||||
"Post comment":
|
||||
"Invia commento",
|
||||
"Sending comment...":
|
||||
"Commento in fase di invio...",
|
||||
"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",
|
||||
"stato 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...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"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>",
|
||||
"Il tuo messaggio è qui: <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Premi [Ctrl]+[c] (Windows) o [Cmd]+[c] (Mac) per copiare il link)</span>",
|
||||
"Delete data":
|
||||
"Cancella i dati",
|
||||
"Could not create paste: %s":
|
||||
"Non rieco a creare il messaggio: %s",
|
||||
"Non riesco 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",
|
||||
|
@ -129,7 +129,8 @@
|
|||
"Source Code": "Codice Sorgente",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Scarica Allegato",
|
||||
"Cloned file attached.": "Copia del file allegata.",
|
||||
"Cloned: '%s'": "Clonato: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "Il file clonato '%s' era allegato a questo messaggio.",
|
||||
"Attach a file": "Allega un file",
|
||||
"Remove attachment": "Rimuovi allegato",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
|
@ -142,10 +143,13 @@
|
|||
"%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",
|
||||
"Decifra",
|
||||
"Enter password":
|
||||
"Inserisci la password",
|
||||
"Loading…": "Loading…",
|
||||
"Loading…": "Carico…",
|
||||
"Decrypting paste…": "Decifro il messaggio…",
|
||||
"Preparing new paste…": "Preparo il nuovo messaggio…",
|
||||
"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)."
|
||||
"Nel caso questo messaggio non scompaia, controlla questa <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">FAQ</a> per trovare informazioni su come risolvere il problema (in Inglese).",
|
||||
"+++ no paste text +++": "+++ nessun testo nel messaggio +++"
|
||||
}
|
||||
|
|
44
i18n/no.json
44
i18n/no.json
|
@ -7,8 +7,8 @@
|
|||
"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 php %s or above to work. Sorry.":
|
||||
"Beklager, %s krever php %s 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.":
|
||||
|
@ -26,13 +26,13 @@
|
|||
"Invalid paste ID.":
|
||||
"Feil innlegg ID.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Innlegg er ikke av type slett-etter-lesing.",
|
||||
"Innlegg er ikke av typen 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.",
|
||||
"Javascript kreves for at %s skal fungere<br />Beklager.",
|
||||
"%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:":
|
||||
|
@ -83,7 +83,7 @@
|
|||
"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.",
|
||||
"Kan ikke slette innlegget, det ble ikke lagret som 'slett etter les' type.",
|
||||
"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?":
|
||||
|
@ -92,30 +92,30 @@
|
|||
"Svar",
|
||||
"Anonymous":
|
||||
"Anonym",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Anonym avatar (Vizhash av IP adressen)",
|
||||
"Avatar generated from IP address":
|
||||
"Anonym avatar generert med data fra IP adressen)",
|
||||
"Add comment":
|
||||
"Legg til kommentar",
|
||||
"Optional nickname...":
|
||||
"Valgfritt kallenavn...",
|
||||
"Optional nickname…":
|
||||
"Valgfritt kallenavn…",
|
||||
"Post comment":
|
||||
"Send kommentar",
|
||||
"Sending comment...":
|
||||
"Sender Kommentar...",
|
||||
"Sending comment…":
|
||||
"Sender Kommentar…",
|
||||
"Comment posted.":
|
||||
"Kommentar sendt.",
|
||||
"Could not refresh display: %s":
|
||||
"Kunne ikke oppdatere skjermen: %s",
|
||||
"Kunne ikke oppdatere bildet: %s",
|
||||
"unknown status":
|
||||
"ukjent status",
|
||||
"server error or not responding":
|
||||
"server feilet eller svarer ikke",
|
||||
"tjener 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...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Flytt musen for mer 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":
|
||||
|
@ -129,14 +129,15 @@
|
|||
"Source Code": "Kildekode",
|
||||
"Markdown": "Oppmerket",
|
||||
"Download attachment": "Last ned vedlegg",
|
||||
"Cloned file attached.": "Kopier vedlegg.",
|
||||
"Cloned: '%s'": "Kopiert: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"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",
|
||||
"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.":
|
||||
|
@ -146,6 +147,9 @@
|
|||
"Enter password":
|
||||
"Skriv inn passord",
|
||||
"Loading…": "Laster…",
|
||||
"Decrypting paste…": "Dekrypterer innlegg…",
|
||||
"Preparing new paste…": "Klargjør nytt innlegg…",
|
||||
"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."
|
||||
"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.",
|
||||
"+++ no paste text +++": "+++ ingen innleggstekst +++"
|
||||
}
|
||||
|
|
30
i18n/oc.json
30
i18n/oc.json
|
@ -7,8 +7,8 @@
|
|||
"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 php %s or above to work. Sorry.":
|
||||
"O planhèm, %s necessita php %s 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.":
|
||||
|
@ -92,16 +92,16 @@
|
|||
"Respondre",
|
||||
"Anonymous":
|
||||
"Anonime",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar generated from IP address":
|
||||
"Avatar anonime (Vizhash de l'adreça IP)",
|
||||
"Add comment":
|
||||
"Apondre un comentari",
|
||||
"Optional nickname...":
|
||||
"Escais opcional...",
|
||||
"Optional nickname…":
|
||||
"Escais opcional…",
|
||||
"Post comment":
|
||||
"Mandar lo comentari",
|
||||
"Sending comment...":
|
||||
"Mandadís del comentari...",
|
||||
"Sending comment…":
|
||||
"Mandadís del comentari…",
|
||||
"Comment posted.":
|
||||
"Comentari mandat.",
|
||||
"Could not refresh display: %s":
|
||||
|
@ -112,10 +112,10 @@
|
|||
"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...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"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":
|
||||
|
@ -138,7 +138,8 @@
|
|||
"Source Code": "Còdi font",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Telecargar la pèça junta",
|
||||
"Cloned file attached.": "Clonar lo fichièr junt.",
|
||||
"Cloned: '%s'": "Clonar: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"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.":
|
||||
|
@ -155,6 +156,9 @@
|
|||
"Enter password":
|
||||
"Picatz lo senhal",
|
||||
"Loading…": "Cargament…",
|
||||
"Decrypting paste…": "Decrypting paste…",
|
||||
"Preparing new paste…": "Preparing new paste…",
|
||||
"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)."
|
||||
"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).",
|
||||
"+++ no paste text +++": "+++ no paste text +++"
|
||||
}
|
||||
|
|
30
i18n/pl.json
30
i18n/pl.json
|
@ -7,8 +7,8 @@
|
|||
"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 php %s or above to work. Sorry.":
|
||||
"%s wymaga PHP w wersji %s 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.":
|
||||
|
@ -92,16 +92,16 @@
|
|||
"Odpowiedz",
|
||||
"Anonymous":
|
||||
"Anonim",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar generated from IP address":
|
||||
"Anonimowy avatar (Vizhash z adresu IP)",
|
||||
"Add comment":
|
||||
"Dodaj komentarz",
|
||||
"Optional nickname...":
|
||||
"Opcjonalny nick...",
|
||||
"Optional nickname…":
|
||||
"Opcjonalny nick…",
|
||||
"Post comment":
|
||||
"Wyślij komentarz",
|
||||
"Sending comment...":
|
||||
"Wysyłanie komentarza...",
|
||||
"Sending comment…":
|
||||
"Wysyłanie komentarza…",
|
||||
"Comment posted.":
|
||||
"Wysłano komentarz.",
|
||||
"Could not refresh display: %s":
|
||||
|
@ -112,10 +112,10 @@
|
|||
"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...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"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":
|
||||
|
@ -129,7 +129,8 @@
|
|||
"Source Code": "Kod źródłowy",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Pobierz załącznik",
|
||||
"Cloned file attached.": "Sklonowano załączony plik.",
|
||||
"Cloned: '%s'": "Sklonowano: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"Attach a file": "Załącz plik",
|
||||
"Remove attachment": "Usuń załącznik",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
|
@ -146,6 +147,9 @@
|
|||
"Enter password":
|
||||
"Wpisz hasło",
|
||||
"Loading…": "Loading…",
|
||||
"Decrypting paste…": "Decrypting paste…",
|
||||
"Preparing new paste…": "Preparing new paste…",
|
||||
"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)."
|
||||
"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).",
|
||||
"+++ no paste text +++": "+++ no paste text +++"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
{
|
||||
"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 é um serviço minimalista e de código aberto do tipo \"pastebin\", em que o servidor tem zero conhecimento dos dados copiados. Os dados são cifrados e decifrados <i>no navegador</i> usando 256 bits AES. Mais informações na <a href=\"https://privatebin.info/\">página do projeto</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Porque a ignorância é uma benção",
|
||||
"en": "pt",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"A cópia não existe, expirou ou já foi excluída.",
|
||||
"%s requires php %s or above to work. Sorry.":
|
||||
"%s requer php %s ou superior para funcionar. Desculpa.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s requer que a seção de configuração [% s] esteja no arquivo de configuração.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Por favor espere %d segundos entre cada publicação.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"A cópia está limitada a %s de dados cifrados.",
|
||||
"Invalid data.":
|
||||
"Dados inválidos.",
|
||||
"You are unlucky. Try again.":
|
||||
"Você é azarado. Tente novamente",
|
||||
"Error saving comment. Sorry.":
|
||||
"Erro ao salvar comentário. Desculpa.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Erro ao salvar cópia. Desculpa.",
|
||||
"Invalid paste ID.":
|
||||
"ID de cópia inválido.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Cópia não é do tipo \"queime após ler\".",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Token de remoção inválido. A cópia não foi excluída.",
|
||||
"Paste was properly deleted.":
|
||||
"A cópia foi devidamente excluída.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"JavaScript é necessário para que %s funcione.<br />Pedimos desculpas pela inconveniência.",
|
||||
"%s requires a modern browser to work.":
|
||||
"%s requer um navegador moderno para funcionar.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Ainda usando Internet Explorer? Faça-se um favor, mude para um navegador moderno:",
|
||||
"New":
|
||||
"Novo",
|
||||
"Send":
|
||||
"Enviar",
|
||||
"Clone":
|
||||
"Clonar",
|
||||
"Raw text":
|
||||
"Texto sem formato",
|
||||
"Expires":
|
||||
"Expirar em",
|
||||
"Burn after reading":
|
||||
"Queime após ler",
|
||||
"Open discussion":
|
||||
"Discussão aberta",
|
||||
"Password (recommended)":
|
||||
"Senha (recomendada)",
|
||||
"Discussion":
|
||||
"Discussão",
|
||||
"Toggle navigation":
|
||||
"Mudar navegação",
|
||||
"%d seconds": ["%d segundo", "%d segundos"],
|
||||
"%d minutes": ["%d minuto", "%d minutos"],
|
||||
"%d hours": ["%d hora", "%d horas"],
|
||||
"%d days": ["%d dia", "%d dias"],
|
||||
"%d weeks": ["%d semana", "%d semanas"],
|
||||
"%d months": ["%d mês", "%d meses"],
|
||||
"%d years": ["%d ano", "%d anos"],
|
||||
"Never":
|
||||
"Nunca",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Nota: Este é um serviço de teste. Dados podem ser perdidos a qualquer momento. Gatinhos morrerão se você abusar desse serviço.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Este documento irá expirar em um segundo.", "Este documento irá expirar em %d segundos."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Este documento irá expirar em um minuto.", "Este documento irá expirar em %d minutos."],
|
||||
"This document will expire in %d hours.":
|
||||
["Este documento irá expirar em uma hora.", "Este documento irá expirar em %d horas."],
|
||||
"This document will expire in %d days.":
|
||||
["Este documento irá expirar em um dia.", "Este documento irá expirar em %d dias."],
|
||||
"This document will expire in %d months.":
|
||||
["Este documento irá expirar em um mês.", "Este documento irá expirar em %d meses."],
|
||||
"Please enter the password for this paste:":
|
||||
"Por favor, digite a senha para essa cópia:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Não foi possível decifrar os dados (Chave errada?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Não foi possível excluir a cópia, ela não foi salva no modo de \"queime após ler\".",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"APENAS PARA SEUS OLHOS. Não feche essa janela, essa mensagem não pode ser exibida novamente.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Não foi possível decifrar o comentário; Chave errada?",
|
||||
"Reply":
|
||||
"Responder",
|
||||
"Anonymous":
|
||||
"Anônimo",
|
||||
"Avatar generated from IP address":
|
||||
"Avatar gerado à partir do endereço IP",
|
||||
"Add comment":
|
||||
"Adicionar comentário",
|
||||
"Optional nickname…":
|
||||
"Apelido opcional…",
|
||||
"Post comment":
|
||||
"Publicar comentário",
|
||||
"Sending comment…":
|
||||
"Enviando comentário…",
|
||||
"Comment posted.":
|
||||
"Comentário publicado.",
|
||||
"Could not refresh display: %s":
|
||||
"Não foi possível atualizar a tela: %s",
|
||||
"unknown status":
|
||||
"Estado desconhecido",
|
||||
"server error or not responding":
|
||||
"Servidor em erro ou não responsivo",
|
||||
"Could not post comment: %s":
|
||||
"Não foi possível publicar o comentário: %s",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Por favor, mova o mouse para maior entropia…",
|
||||
"Sending paste…":
|
||||
"Enviando cópia…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Sua cópia é <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Pressione [Ctrl]+[c] para copiar)</span>",
|
||||
"Delete data":
|
||||
"Excluir dados",
|
||||
"Could not create paste: %s":
|
||||
"Não foi possível criar cópia: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Não foi possível decifrar a cópia: chave de decriptografia ausente na URL (Você utilizou um redirecionador ou encurtador de URL que removeu parte dela?)",
|
||||
"Format": "Formato",
|
||||
"Plain Text": "Texto sem formato",
|
||||
"Source Code": "Código fonte",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Baixar anexo",
|
||||
"Cloned: '%s'": "Clonado: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "O arquivo clonado '%s' foi anexado a essa cópia.",
|
||||
"Attach a file": "Anexar um arquivo",
|
||||
"Remove attachment": "Remover anexo",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Seu navegador não permite subir arquivos cifrados. Por favor, utilize um navegador mais recente.",
|
||||
"Invalid attachment.": "Anexo inválido.",
|
||||
"Options": "Opções",
|
||||
"Shorten URL": "Encurtar URL",
|
||||
"Editor": "Editor",
|
||||
"Preview": "Visualizar",
|
||||
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
|
||||
"%s requer que o PATH termine em \"%s\". Por favor, atualize o PATH em seu index.php.",
|
||||
"Decrypt":
|
||||
"Decifrar",
|
||||
"Enter password":
|
||||
"Digite a senha",
|
||||
"Loading…": "Carregando…",
|
||||
"Decrypting paste…": "Decifrando cópia…",
|
||||
"Preparing new paste…": "Preparando nova cópia…",
|
||||
"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>.":
|
||||
"Caso essa mensagem nunca desapareça, por favor veja <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">este FAQ para saber como resolver os problemas</a>.",
|
||||
"+++ no paste text +++": "+++ sem texto de cópia +++"
|
||||
}
|
40
i18n/ru.json
40
i18n/ru.json
|
@ -7,8 +7,8 @@
|
|||
"en": "ru",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Запись не существует, просрочена или была удалена.",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"Для работы %s требуется PHP 5.3.0 или выше. Извините.",
|
||||
"%s requires php %s or above to work. Sorry.":
|
||||
"Для работы %s требуется php %s или выше. Извините.",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s необходимо наличие секции [%s] в конфигурационном файле.",
|
||||
"Please wait %d seconds between each post.":
|
||||
|
@ -32,7 +32,7 @@
|
|||
"Paste was properly deleted.":
|
||||
"Запись была успешно удалена.",
|
||||
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
|
||||
"Для работы %s требуется включенный JavaScript.<br />Приносим извинения за неудобства..",
|
||||
"Для работы %s требуется включенный JavaScript.<br />Приносим извинения за неудобства.",
|
||||
"%s requires a modern browser to work.":
|
||||
"Для работы %s требуется более современный браузер.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
|
@ -92,30 +92,30 @@
|
|||
"Ответить",
|
||||
"Anonymous":
|
||||
"Аноним",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Анонимный аватар (Vizhash IP адреса)",
|
||||
"Avatar generated from IP address":
|
||||
"Аватар, сгенерированный из IP-адреса",
|
||||
"Add comment":
|
||||
"Добавить комментарий",
|
||||
"Optional nickname...":
|
||||
"Опциональный никнейм...",
|
||||
"Optional nickname…":
|
||||
"Опциональный никнейм…",
|
||||
"Post comment":
|
||||
"Отправить комментарий",
|
||||
"Sending comment...":
|
||||
"Отправка комментария...",
|
||||
"Sending comment…":
|
||||
"Отправка комментария…",
|
||||
"Comment posted.":
|
||||
"Комментарий опубликован.",
|
||||
"Could not refresh display: %s":
|
||||
"Невозможно обновить данные: %s",
|
||||
"Не удалось обновить отображение: %s",
|
||||
"unknown status":
|
||||
"неизвестная причина",
|
||||
"server error or not responding":
|
||||
"ошибка сервера или нет ответа",
|
||||
"Could not post comment: %s":
|
||||
"Не удалось опубликовать комментарий: %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Отправка записи (Пожалуйста двигайте мышкой для большей энтропии)...",
|
||||
"Sending paste...":
|
||||
"Отправка записи...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"Пожалуйста двигайте мышкой для большей энтропии…",
|
||||
"Sending paste…":
|
||||
"Отправка записи…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Ссылка на запись <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Нажмите [Ctrl]+[c] чтобы скопировать ссылку)</span>",
|
||||
"Delete data":
|
||||
|
@ -138,7 +138,9 @@
|
|||
"Source Code": "Исходный код",
|
||||
"Markdown": "Язык разметки",
|
||||
"Download attachment": "Скачать прикрепленный файл",
|
||||
"Cloned file attached.": "Дубль файла прикреплен.",
|
||||
"Cloned: '%s'": "Дублировано: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.":
|
||||
"Дубликат файла '%s' был прикреплен к этой записи.",
|
||||
"Attach a file": "Прикрепить файл",
|
||||
"Remove attachment": "Удалить вложение",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
|
@ -154,6 +156,10 @@
|
|||
"Расшифровать",
|
||||
"Enter password":
|
||||
"Введите пароль",
|
||||
"Uploading paste… Please wait.":
|
||||
"Отправка записи... Пожалуйста подождите."
|
||||
"Loading…": "Загрузка…",
|
||||
"Decrypting paste…": "Расшифровка записи…",
|
||||
"Preparing new paste…": "Подготовка новой записи…",
|
||||
"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>.":
|
||||
"Если данное сообщение не исчезает длительное время, посмотрите <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">этот FAQ с информацией о возможном решении проблемы (на английском)</a>.",
|
||||
"+++ no paste text +++": "+++ в записи нет текста +++"
|
||||
}
|
||||
|
|
28
i18n/sl.json
28
i18n/sl.json
|
@ -7,8 +7,8 @@
|
|||
"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 php %s or above to work. Sorry.":
|
||||
"Oprosti, %s za delovanje potrebuje vsaj php %s.",
|
||||
"%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.":
|
||||
|
@ -92,16 +92,16 @@
|
|||
"Odgovori",
|
||||
"Anonymous":
|
||||
"Aninomno",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar generated from IP address":
|
||||
"Anonimen avatar (Vizhash IP naslova)",
|
||||
"Add comment":
|
||||
"Dodaj komentar",
|
||||
"Optional nickname...":
|
||||
"Optional nickname…":
|
||||
"Uporabniško ime (lahko izpustiš)",
|
||||
"Post comment":
|
||||
"Objavi komentar",
|
||||
"Sending comment...":
|
||||
"Pošiljam komentar ...",
|
||||
"Sending comment…":
|
||||
"Pošiljam komentar …",
|
||||
"Comment posted.":
|
||||
"Komentar poslan.",
|
||||
"Could not refresh display: %s":
|
||||
|
@ -112,10 +112,10 @@
|
|||
"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...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"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":
|
||||
|
@ -138,7 +138,8 @@
|
|||
"Source Code": "Odprta koda",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Pretoči priponko",
|
||||
"Cloned file attached.": "Pripeta datoteka klonirana",
|
||||
"Cloned: '%s'": "'%s' klonirana",
|
||||
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
|
||||
"Attach a file": "Pripni datoteko",
|
||||
"Remove attachment": "Odstrani priponko",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
|
@ -155,6 +156,9 @@
|
|||
"Enter password":
|
||||
"Prosim vnesi geslo",
|
||||
"Loading…": "Loading…",
|
||||
"Decrypting paste…": "Decrypting paste…",
|
||||
"Preparing new paste…": "Preparing new paste…",
|
||||
"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)."
|
||||
"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).",
|
||||
"+++ no paste text +++": "+++ no paste text +++"
|
||||
}
|
||||
|
|
44
i18n/zh.json
44
i18n/zh.json
|
@ -7,8 +7,8 @@
|
|||
"en": "zh",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"粘贴不存在,已过期或者已被删除。",
|
||||
"%s requires php 5.3.0 or above to work. Sorry.":
|
||||
"%s需要工作于PHP 5.3.0及以上版本,抱歉。",
|
||||
"%s requires php %s or above to work. Sorry.":
|
||||
"%s需要工作于PHP %s及以上版本,抱歉。",
|
||||
"%s requires configuration section [%s] to be present in configuration file.":
|
||||
"%s需要设置配置文件中 [%s] 的部分。",
|
||||
"Please wait %d seconds between each post.":
|
||||
|
@ -92,16 +92,16 @@
|
|||
"回复",
|
||||
"Anonymous":
|
||||
"匿名",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"匿名头像 (由IP地址生成Vizhash)",
|
||||
"Avatar generated from IP address":
|
||||
"由IP生成的头像",
|
||||
"Add comment":
|
||||
"添加评论",
|
||||
"Optional nickname...":
|
||||
"可选昵称...",
|
||||
"Optional nickname…":
|
||||
"可选昵称…",
|
||||
"Post comment":
|
||||
"评论",
|
||||
"Sending comment...":
|
||||
"评论发送中...",
|
||||
"Sending comment…":
|
||||
"评论发送中…",
|
||||
"Comment posted.":
|
||||
"评论已发送。",
|
||||
"Could not refresh display: %s":
|
||||
|
@ -112,10 +112,10 @@
|
|||
"服务器错误或无回应",
|
||||
"Could not post comment: %s":
|
||||
"无法发送评论: %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"粘贴提交中 (请移动鼠标以产生更多熵)...",
|
||||
"Sending paste...":
|
||||
"粘贴提交中...",
|
||||
"Please move your mouse for more entropy…":
|
||||
"请移动鼠标增加随机性…",
|
||||
"Sending paste…":
|
||||
"粘贴提交中…",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"您的粘贴的链接是<a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(按下 [Ctrl]+[c] 以复制)</span>",
|
||||
"Delete data":
|
||||
|
@ -129,7 +129,8 @@
|
|||
"Source Code": "源代码",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "下载附件",
|
||||
"Cloned file attached.": "已附加克隆的文件",
|
||||
"Cloned: '%s'": "克隆: '%s'",
|
||||
"The cloned file '%s' was attached to this paste.": "克隆文件 '%s' 已附加到此粘贴。",
|
||||
"Attach a file": "添加一个附件",
|
||||
"Remove attachment": "移除附件",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
|
@ -137,15 +138,18 @@
|
|||
"Invalid attachment.": "无效的附件",
|
||||
"Options": "选项",
|
||||
"Shorten URL": "缩短链接",
|
||||
"Editor": "編輯",
|
||||
"Preview": "預習",
|
||||
"Editor": "编辑",
|
||||
"Preview": "预览",
|
||||
"%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.",
|
||||
"%s 的 PATH 变量必须结束于 \"%s\"。 请修改你的 index.php 中的 PATH 变量。",
|
||||
"Decrypt":
|
||||
"Decrypt",
|
||||
"解密",
|
||||
"Enter password":
|
||||
"Enter password",
|
||||
"Loading…": "Loading…",
|
||||
"输入密码",
|
||||
"Loading…": "载入中…",
|
||||
"Decrypting paste…": "正在解密",
|
||||
"Preparing new paste…": "正在准备新的粘贴",
|
||||
"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)."
|
||||
"如果这个消息一直不消失,请参考 <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">这里的 FAQ 进行故障排除</a> (英文版)。",
|
||||
"+++ no paste text +++": "+++ 没有粘贴内容 +++"
|
||||
}
|
||||
|
|
5028
js/privatebin.js
5028
js/privatebin.js
File diff suppressed because it is too large
Load Diff
387
js/test.js
387
js/test.js
|
@ -11,7 +11,9 @@ var jsc = require('jsverify'),
|
|||
a2zString.map(function(c) {
|
||||
return c.toUpperCase();
|
||||
})
|
||||
);
|
||||
),
|
||||
// schemas supported by the whatwg-url library
|
||||
schemas = ['ftp','gopher','http','https','ws','wss'];
|
||||
|
||||
global.$ = global.jQuery = require('./jquery-3.1.1');
|
||||
global.sjcl = require('./sjcl-1.0.6');
|
||||
|
@ -20,127 +22,293 @@ global.RawDeflate = require('./rawdeflate-0.5');
|
|||
require('./rawinflate-0.3');
|
||||
require('./privatebin');
|
||||
|
||||
describe('helper', function () {
|
||||
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);
|
||||
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;
|
||||
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';
|
||||
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);
|
||||
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';
|
||||
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));
|
||||
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';
|
||||
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));
|
||||
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';
|
||||
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));
|
||||
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';
|
||||
return $.PrivateBin.Helper.secondsToHuman(number)[1] === 'month';
|
||||
});
|
||||
});
|
||||
|
||||
describe('scriptLocation', function () {
|
||||
// this test is not yet meaningful using jsdom, as it does not contain getSelection support.
|
||||
// TODO: This needs to be tested using a browser.
|
||||
describe('selectText', function () {
|
||||
jsc.property(
|
||||
'selection contains content of given ID',
|
||||
jsc.nearray(jsc.nearray(jsc.elements(alnumString))),
|
||||
'nearray string',
|
||||
function (ids, contents) {
|
||||
var html = '',
|
||||
result = true;
|
||||
ids.forEach(function(item, i) {
|
||||
html += '<div id="' + item.join('') + '">' + $.PrivateBin.Helper.htmlEntities(contents[i] || contents[0]) + '</div>';
|
||||
});
|
||||
var clean = jsdom(html);
|
||||
ids.forEach(function(item, i) {
|
||||
$.PrivateBin.Helper.selectText(item.join(''));
|
||||
// TODO: As per https://github.com/tmpvar/jsdom/issues/321 there is no getSelection in jsdom, yet.
|
||||
// Once there is one, uncomment the line below to actually check the result.
|
||||
//result *= (contents[i] || contents[0]) === window.getSelection().toString();
|
||||
});
|
||||
clean();
|
||||
return Boolean(result);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('setElementText', function () {
|
||||
after(function () {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
jsc.property(
|
||||
'replaces the content of an element',
|
||||
jsc.nearray(jsc.nearray(jsc.elements(alnumString))),
|
||||
'nearray string',
|
||||
'string',
|
||||
function (ids, contents, replacingContent) {
|
||||
var html = '',
|
||||
result = true;
|
||||
ids.forEach(function(item, i) {
|
||||
html += '<div id="' + item.join('') + '">' + $.PrivateBin.Helper.htmlEntities(contents[i] || contents[0]) + '</div>';
|
||||
});
|
||||
var elements = $('<body />').html(html);
|
||||
ids.forEach(function(item, i) {
|
||||
var id = item.join(''),
|
||||
element = elements.find('#' + id).first();
|
||||
$.PrivateBin.Helper.setElementText(element, replacingContent);
|
||||
result *= replacingContent === element.text();
|
||||
});
|
||||
return Boolean(result);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('urls2links', function () {
|
||||
after(function () {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
jsc.property(
|
||||
'ignores non-URL content',
|
||||
'string',
|
||||
function (content) {
|
||||
var element = $('<div>' + content + '</div>'),
|
||||
before = element.html();
|
||||
$.PrivateBin.Helper.urls2links(element);
|
||||
return before === element.html();
|
||||
}
|
||||
);
|
||||
jsc.property(
|
||||
'replaces URLs with anchors',
|
||||
'string',
|
||||
jsc.elements(['http', 'https', 'ftp']),
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.array(jsc.elements(queryString)),
|
||||
jsc.array(jsc.elements(queryString)),
|
||||
'string',
|
||||
function (prefix, schema, address, query, fragment, postfix) {
|
||||
var query = query.join(''),
|
||||
fragment = fragment.join(''),
|
||||
url = schema + '://' + address.join('') + '/?' + query + '#' + fragment,
|
||||
prefix = $.PrivateBin.Helper.htmlEntities(prefix),
|
||||
postfix = ' ' + $.PrivateBin.Helper.htmlEntities(postfix),
|
||||
element = $('<div>' + prefix + url + postfix + '</div>');
|
||||
|
||||
// special cases: When the query string and fragment imply the beginning of an HTML entity, eg. � or &#x
|
||||
if (
|
||||
query.slice(-1) === '&' &&
|
||||
(parseInt(fragment.substring(0, 1), 10) >= 0 || fragment.charAt(0) === 'x' )
|
||||
)
|
||||
{
|
||||
url = schema + '://' + address.join('') + '/?' + query.substring(0, query.length - 1);
|
||||
postfix = '';
|
||||
element = $('<div>' + prefix + url + '</div>');
|
||||
}
|
||||
|
||||
$.PrivateBin.Helper.urls2links(element);
|
||||
return element.html() === $('<div>' + prefix + '<a href="' + url + '" rel="nofollow">' + url + '</a>' + postfix + '</div>').html();
|
||||
}
|
||||
);
|
||||
jsc.property(
|
||||
'replaces magnet links with anchors',
|
||||
'string',
|
||||
jsc.array(jsc.elements(queryString)),
|
||||
'string',
|
||||
function (prefix, query, postfix) {
|
||||
var url = 'magnet:?' + query.join(''),
|
||||
prefix = $.PrivateBin.Helper.htmlEntities(prefix),
|
||||
postfix = $.PrivateBin.Helper.htmlEntities(postfix),
|
||||
element = $('<div>' + prefix + url + ' ' + postfix + '</div>');
|
||||
$.PrivateBin.Helper.urls2links(element);
|
||||
return element.html() === $('<div>' + prefix + '<a href="' + url + '" rel="nofollow">' + url + '</a> ' + postfix + '</div>').html();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('sprintf', function () {
|
||||
after(function () {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
jsc.property(
|
||||
'replaces %s in strings with first given parameter',
|
||||
'string',
|
||||
'(small nearray) string',
|
||||
'string',
|
||||
function (prefix, params, postfix) {
|
||||
var prefix = prefix.replace(/%(s|d)/g, '%%'),
|
||||
postfix = postfix.replace(/%(s|d)/g, '%%'),
|
||||
result = prefix + params[0] + postfix;
|
||||
params.unshift(prefix + '%s' + postfix);
|
||||
return result === $.PrivateBin.Helper.sprintf.apply(this, params);
|
||||
}
|
||||
);
|
||||
jsc.property(
|
||||
'replaces %d in strings with first given parameter',
|
||||
'string',
|
||||
'(small nearray) nat',
|
||||
'string',
|
||||
function (prefix, params, postfix) {
|
||||
var prefix = prefix.replace(/%(s|d)/g, '%%'),
|
||||
postfix = postfix.replace(/%(s|d)/g, '%%'),
|
||||
result = prefix + params[0] + postfix;
|
||||
params.unshift(prefix + '%d' + postfix);
|
||||
return result === $.PrivateBin.Helper.sprintf.apply(this, params);
|
||||
}
|
||||
);
|
||||
jsc.property(
|
||||
'replaces %d in strings with 0 if first parameter is not a number',
|
||||
'string',
|
||||
'(small nearray) falsy',
|
||||
'string',
|
||||
function (prefix, params, postfix) {
|
||||
var prefix = prefix.replace(/%(s|d)/g, '%%'),
|
||||
postfix = postfix.replace(/%(s|d)/g, '%%'),
|
||||
result = prefix + '0' + postfix;
|
||||
params.unshift(prefix + '%d' + postfix);
|
||||
return result === $.PrivateBin.Helper.sprintf.apply(this, params)
|
||||
}
|
||||
);
|
||||
jsc.property(
|
||||
'replaces %d and %s in strings in order',
|
||||
'string',
|
||||
'nat',
|
||||
'string',
|
||||
'string',
|
||||
'string',
|
||||
function (prefix, uint, middle, string, postfix) {
|
||||
var prefix = prefix.replace(/%(s|d)/g, '%%'),
|
||||
postfix = postfix.replace(/%(s|d)/g, '%%'),
|
||||
params = [prefix + '%d' + middle + '%s' + postfix, uint, string],
|
||||
result = prefix + uint + middle + string + postfix;
|
||||
return result === $.PrivateBin.Helper.sprintf.apply(this, params);
|
||||
}
|
||||
);
|
||||
jsc.property(
|
||||
'replaces %d and %s in strings in reverse order',
|
||||
'string',
|
||||
'nat',
|
||||
'string',
|
||||
'string',
|
||||
'string',
|
||||
function (prefix, uint, middle, string, postfix) {
|
||||
var prefix = prefix.replace(/%(s|d)/g, '%%'),
|
||||
postfix = postfix.replace(/%(s|d)/g, '%%'),
|
||||
params = [prefix + '%s' + middle + '%d' + postfix, string, uint],
|
||||
result = prefix + string + middle + uint + postfix;
|
||||
return result === $.PrivateBin.Helper.sprintf.apply(this, params);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('getCookie', function () {
|
||||
jsc.property(
|
||||
'returns the requested cookie',
|
||||
'nearray asciinestring',
|
||||
'nearray asciistring',
|
||||
function (labels, values) {
|
||||
var selectedKey = '', selectedValue = '',
|
||||
cookieArray = [],
|
||||
count = 0;
|
||||
labels.forEach(function(item, i) {
|
||||
var key = item.replace(/[\s;,=]/g, 'x'),
|
||||
value = (values[i] || values[0]).replace(/[\s;,=]/g, '');
|
||||
cookieArray.push(key + '=' + value);
|
||||
if (Math.random() < 1 / i)
|
||||
{
|
||||
selectedKey = key;
|
||||
selectedValue = value;
|
||||
}
|
||||
});
|
||||
var clean = jsdom('', {cookie: cookieArray}),
|
||||
result = $.PrivateBin.Helper.getCookie(selectedKey);
|
||||
clean();
|
||||
return result === selectedValue;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('baseUri', function () {
|
||||
before(function () {
|
||||
$.PrivateBin.Helper.reset();
|
||||
});
|
||||
|
||||
jsc.property(
|
||||
'returns the URL without query & fragment',
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.elements(schemas),
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.array(jsc.elements(queryString)),
|
||||
'string',
|
||||
function (schema, address, query, fragment) {
|
||||
var expected = schema.join('') + '://' + address.join('') + '/',
|
||||
var expected = schema + '://' + address.join('') + '/',
|
||||
clean = jsdom('', {url: expected + '?' + query.join('') + '#' + fragment}),
|
||||
result = $.PrivateBin.helper.scriptLocation();
|
||||
result = $.PrivateBin.Helper.baseUri();
|
||||
$.PrivateBin.Helper.reset();
|
||||
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();
|
||||
|
@ -150,9 +318,76 @@ describe('helper', function () {
|
|||
'removes all HTML entities from any given string',
|
||||
'string',
|
||||
function (string) {
|
||||
var result = $.PrivateBin.helper.htmlEntities(string);
|
||||
var result = $.PrivateBin.Helper.htmlEntities(string);
|
||||
return !(/[<>"'`=\/]/.test(result)) && !(string.indexOf('&') > -1 && !(/&/.test(result)));
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model', function () {
|
||||
describe('getPasteId', function () {
|
||||
before(function () {
|
||||
$.PrivateBin.Model.reset();
|
||||
});
|
||||
|
||||
jsc.property(
|
||||
'returns the query string without separator, if any',
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.nearray(jsc.elements(a2zString)),
|
||||
jsc.nearray(jsc.elements(queryString)),
|
||||
'string',
|
||||
function (schema, address, query, fragment) {
|
||||
var queryString = query.join(''),
|
||||
clean = jsdom('', {
|
||||
url: schema.join('') + '://' + address.join('') +
|
||||
'/?' + queryString + '#' + fragment
|
||||
}),
|
||||
result = $.PrivateBin.Model.getPasteId();
|
||||
$.PrivateBin.Model.reset();
|
||||
clean();
|
||||
return queryString === result;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('getPasteKey', 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.nearray(jsc.elements(base64String)),
|
||||
function (schema, address, query, fragment) {
|
||||
var fragmentString = fragment.join(''),
|
||||
clean = jsdom('', {
|
||||
url: schema.join('') + '://' + address.join('') +
|
||||
'/?' + query.join('') + '#' + fragmentString
|
||||
}),
|
||||
result = $.PrivateBin.Model.getPasteKey();
|
||||
$.PrivateBin.Model.reset();
|
||||
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.nearray(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.Model.getPasteKey();
|
||||
$.PrivateBin.Model.reset();
|
||||
clean();
|
||||
return fragmentString === result;
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
Allow from none
|
||||
Deny from all
|
||||
Require all denied
|
||||
|
|
|
@ -58,7 +58,7 @@ abstract class AbstractData
|
|||
* @access public
|
||||
* @static
|
||||
* @param array $options
|
||||
* @return privatebin_abstract
|
||||
* @return AbstractData
|
||||
*/
|
||||
public static function getInstance($options)
|
||||
{
|
||||
|
@ -88,7 +88,6 @@ abstract class AbstractData
|
|||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return void
|
||||
*/
|
||||
abstract public function delete($pasteid);
|
||||
|
||||
|
@ -147,7 +146,6 @@ abstract class AbstractData
|
|||
*
|
||||
* @access public
|
||||
* @param int $batchsize
|
||||
* @return void
|
||||
*/
|
||||
public function purge($batchsize)
|
||||
{
|
||||
|
|
|
@ -282,7 +282,6 @@ class Database extends AbstractData
|
|||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return void
|
||||
*/
|
||||
public function delete($pasteid)
|
||||
{
|
||||
|
@ -375,11 +374,10 @@ class Database extends AbstractData
|
|||
$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'];
|
||||
foreach (array('nickname', 'vizhash') as $key) {
|
||||
if (array_key_exists($key, $row) && !empty($row[$key])) {
|
||||
$comments[$i]->meta->$key = $row[$key];
|
||||
}
|
||||
if (array_key_exists('vizhash', $row) && !empty($row['vizhash'])) {
|
||||
$comments[$i]->meta->vizhash = $row['vizhash'];
|
||||
}
|
||||
}
|
||||
ksort($comments);
|
||||
|
@ -564,7 +562,6 @@ class Database extends AbstractData
|
|||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
private static function _createPasteTable()
|
||||
{
|
||||
|
@ -589,7 +586,6 @@ class Database extends AbstractData
|
|||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
private static function _createCommentTable()
|
||||
{
|
||||
|
@ -616,7 +612,6 @@ class Database extends AbstractData
|
|||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
private static function _createConfigTable()
|
||||
{
|
||||
|
@ -651,7 +646,6 @@ class Database extends AbstractData
|
|||
* @access private
|
||||
* @static
|
||||
* @param string $oldversion
|
||||
* @return void
|
||||
*/
|
||||
private static function _upgradeDatabase($oldversion)
|
||||
{
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
namespace PrivateBin\Data;
|
||||
|
||||
use PrivateBin\Json;
|
||||
use PrivateBin\Model\Paste;
|
||||
use PrivateBin\Persistence\DataStore;
|
||||
|
||||
/**
|
||||
* Filesystem
|
||||
|
@ -22,15 +22,6 @@ use PrivateBin\Model\Paste;
|
|||
*/
|
||||
class Filesystem extends AbstractData
|
||||
{
|
||||
/**
|
||||
* directory where data is stored
|
||||
*
|
||||
* @access private
|
||||
* @static
|
||||
* @var string
|
||||
*/
|
||||
private static $_dir = 'data/';
|
||||
|
||||
/**
|
||||
* get instance of singleton
|
||||
*
|
||||
|
@ -41,17 +32,16 @@ class Filesystem extends AbstractData
|
|||
*/
|
||||
public static function getInstance($options = null)
|
||||
{
|
||||
// if needed initialize the singleton
|
||||
if (!(self::$_instance instanceof self)) {
|
||||
self::$_instance = new self;
|
||||
}
|
||||
// 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();
|
||||
DataStore::setPath($options['dir']);
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
@ -62,19 +52,19 @@ class Filesystem extends AbstractData
|
|||
* @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)) {
|
||||
$file = $storagedir . $pasteid;
|
||||
if (is_file($file)) {
|
||||
return false;
|
||||
}
|
||||
if (!is_dir($storagedir)) {
|
||||
mkdir($storagedir, 0700, true);
|
||||
}
|
||||
return (bool) file_put_contents($storagedir . $pasteid, Json::encode($paste));
|
||||
return DataStore::store($file, $paste);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,7 +98,6 @@ class Filesystem extends AbstractData
|
|||
*
|
||||
* @access public
|
||||
* @param string $pasteid
|
||||
* @return void
|
||||
*/
|
||||
public function delete($pasteid)
|
||||
{
|
||||
|
@ -155,20 +144,19 @@ class Filesystem extends AbstractData
|
|||
* @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)) {
|
||||
$file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid;
|
||||
if (is_file($file)) {
|
||||
return false;
|
||||
}
|
||||
if (!is_dir($storagedir)) {
|
||||
mkdir($storagedir, 0700, true);
|
||||
}
|
||||
return (bool) file_put_contents($storagedir . $filename, Json::encode($comment));
|
||||
return DataStore::store($file, $comment);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,8 +225,9 @@ class Filesystem extends AbstractData
|
|||
protected function _getExpiredPastes($batchsize)
|
||||
{
|
||||
$pastes = array();
|
||||
$mainpath = DataStore::getPath();
|
||||
$firstLevel = array_filter(
|
||||
scandir(self::$_dir),
|
||||
scandir($mainpath),
|
||||
'self::_isFirstLevelDir'
|
||||
);
|
||||
if (count($firstLevel) > 0) {
|
||||
|
@ -246,7 +235,7 @@ class Filesystem extends AbstractData
|
|||
for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) {
|
||||
$firstKey = array_rand($firstLevel);
|
||||
$secondLevel = array_filter(
|
||||
scandir(self::$_dir . $firstLevel[$firstKey]),
|
||||
scandir($mainpath . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]),
|
||||
'self::_isSecondLevelDir'
|
||||
);
|
||||
|
||||
|
@ -257,8 +246,9 @@ class Filesystem extends AbstractData
|
|||
}
|
||||
|
||||
$secondKey = array_rand($secondLevel);
|
||||
$path = self::$_dir . $firstLevel[$firstKey] .
|
||||
DIRECTORY_SEPARATOR . $secondLevel[$secondKey];
|
||||
$path = $mainpath . DIRECTORY_SEPARATOR .
|
||||
$firstLevel[$firstKey] . DIRECTORY_SEPARATOR .
|
||||
$secondLevel[$secondKey];
|
||||
if (!is_dir($path)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -292,29 +282,6 @@ class Filesystem extends AbstractData
|
|||
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.
|
||||
*
|
||||
|
@ -332,8 +299,10 @@ class Filesystem extends AbstractData
|
|||
*/
|
||||
private static function _dataid2path($dataid)
|
||||
{
|
||||
return self::$_dir . substr($dataid, 0, 2) . DIRECTORY_SEPARATOR .
|
||||
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR;
|
||||
return DataStore::getPath(
|
||||
substr($dataid, 0, 2) . DIRECTORY_SEPARATOR .
|
||||
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -363,7 +332,7 @@ class Filesystem extends AbstractData
|
|||
private static function _isFirstLevelDir($element)
|
||||
{
|
||||
return self::_isSecondLevelDir($element) &&
|
||||
is_dir(self::$_dir . DIRECTORY_SEPARATOR . $element);
|
||||
is_dir(DataStore::getPath($element));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,21 +21,6 @@ use Exception;
|
|||
*/
|
||||
class Filter
|
||||
{
|
||||
/**
|
||||
* strips slashes deeply
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public static function stripslashesDeep($value)
|
||||
{
|
||||
return is_array($value) ?
|
||||
array_map('self::stripslashesDeep', $value) :
|
||||
stripslashes($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* format a given time string into a human readable label (localized)
|
||||
*
|
||||
|
|
11
lib/I18n.php
11
lib/I18n.php
|
@ -135,15 +135,17 @@ class I18n
|
|||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
public static function loadTranslations()
|
||||
{
|
||||
$availableLanguages = self::getAvailableLanguages();
|
||||
|
||||
// check if the lang cookie was set and that language exists
|
||||
if (array_key_exists('lang', $_COOKIE) && in_array($_COOKIE['lang'], $availableLanguages)) {
|
||||
$match = $_COOKIE['lang'];
|
||||
if (
|
||||
array_key_exists('lang', $_COOKIE) &&
|
||||
($key = array_search($_COOKIE['lang'], $availableLanguages)) !== false
|
||||
) {
|
||||
$match = $availableLanguages[$key];
|
||||
}
|
||||
// find a translation file matching the browsers language preferences
|
||||
else {
|
||||
|
@ -256,7 +258,6 @@ class I18n
|
|||
* @access public
|
||||
* @static
|
||||
* @param string $lang
|
||||
* @return void
|
||||
*/
|
||||
public static function setLanguageFallback($lang)
|
||||
{
|
||||
|
@ -304,7 +305,7 @@ class I18n
|
|||
return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
|
||||
case 'sl':
|
||||
return $n % 100 == 1 ? 1 : ($n % 100 == 2 ? 2 : ($n % 100 == 3 || $n % 100 == 4 ? 3 : 0));
|
||||
// de, en, es, it, no
|
||||
// de, en, es, it, no, pt
|
||||
default:
|
||||
return $n != 1 ? 1 : 0;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ class Model
|
|||
* Factory constructor.
|
||||
*
|
||||
* @param configuration $conf
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Configuration $conf)
|
||||
{
|
||||
|
@ -64,8 +63,6 @@ class Model
|
|||
|
||||
/**
|
||||
* Checks if a purge is necessary and triggers it if yes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function purge()
|
||||
{
|
||||
|
|
|
@ -63,7 +63,6 @@ abstract class AbstractModel
|
|||
* @access public
|
||||
* @param Configuration $configuration
|
||||
* @param AbstractData $storage
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Configuration $configuration, AbstractData $storage)
|
||||
{
|
||||
|
@ -90,7 +89,6 @@ abstract class AbstractModel
|
|||
* @access public
|
||||
* @param string $id
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
|
@ -106,7 +104,6 @@ abstract class AbstractModel
|
|||
* @access public
|
||||
* @param string $data
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setData($data)
|
||||
{
|
||||
|
@ -133,7 +130,6 @@ abstract class AbstractModel
|
|||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
abstract public function store();
|
||||
|
||||
|
@ -142,7 +138,6 @@ abstract class AbstractModel
|
|||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
abstract public function delete();
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ class Comment extends AbstractModel
|
|||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
|
@ -101,7 +100,6 @@ class Comment extends AbstractModel
|
|||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
|
@ -129,7 +127,6 @@ class Comment extends AbstractModel
|
|||
* @access public
|
||||
* @param Paste $paste
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setPaste(Paste $paste)
|
||||
{
|
||||
|
@ -154,7 +151,6 @@ class Comment extends AbstractModel
|
|||
* @access public
|
||||
* @param string $id
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setParentId($id)
|
||||
{
|
||||
|
@ -184,7 +180,6 @@ class Comment extends AbstractModel
|
|||
* @access public
|
||||
* @param string $nickname
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setNickname($nickname)
|
||||
{
|
||||
|
|
|
@ -75,7 +75,6 @@ class Paste extends AbstractModel
|
|||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
|
@ -103,7 +102,6 @@ class Paste extends AbstractModel
|
|||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
|
@ -183,7 +181,6 @@ class Paste extends AbstractModel
|
|||
* @access public
|
||||
* @param string $attachment
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setAttachment($attachment)
|
||||
{
|
||||
|
@ -199,7 +196,6 @@ class Paste extends AbstractModel
|
|||
* @access public
|
||||
* @param string $attachmentname
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setAttachmentName($attachmentname)
|
||||
{
|
||||
|
@ -214,7 +210,6 @@ class Paste extends AbstractModel
|
|||
*
|
||||
* @access public
|
||||
* @param string $expiration
|
||||
* @return void
|
||||
*/
|
||||
public function setExpiration($expiration)
|
||||
{
|
||||
|
@ -236,7 +231,6 @@ class Paste extends AbstractModel
|
|||
* @access public
|
||||
* @param string $burnafterreading
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setBurnafterreading($burnafterreading = '1')
|
||||
{
|
||||
|
@ -257,7 +251,6 @@ class Paste extends AbstractModel
|
|||
* @access public
|
||||
* @param string $opendiscussion
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setOpendiscussion($opendiscussion = '1')
|
||||
{
|
||||
|
@ -281,7 +274,6 @@ class Paste extends AbstractModel
|
|||
* @access public
|
||||
* @param string $format
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function setFormatter($format)
|
||||
{
|
||||
|
|
|
@ -36,7 +36,6 @@ abstract class AbstractPersistence
|
|||
* @access public
|
||||
* @static
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public static function setPath($path)
|
||||
{
|
||||
|
@ -80,27 +79,23 @@ abstract class AbstractPersistence
|
|||
* @access protected
|
||||
* @static
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
protected static function _initialize()
|
||||
{
|
||||
// Create storage directory if it does not exist.
|
||||
if (!is_dir(self::$_path)) {
|
||||
if (!@mkdir(self::$_path)) {
|
||||
if (!@mkdir(self::$_path, 0700)) {
|
||||
throw new Exception('unable to create directory ' . self::$_path, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// Create .htaccess file if it does not exist.
|
||||
$file = self::$_path . DIRECTORY_SEPARATOR . '.htaccess';
|
||||
if (!is_file($file)) {
|
||||
$writtenBytes = @file_put_contents(
|
||||
$file,
|
||||
'Allow from none' . PHP_EOL .
|
||||
'Deny from all' . PHP_EOL,
|
||||
'Require all denied' . PHP_EOL,
|
||||
LOCK_EX
|
||||
);
|
||||
if ($writtenBytes === false || $writtenBytes < 30) {
|
||||
if ($writtenBytes === false || $writtenBytes < 19) {
|
||||
throw new Exception('unable to write to file ' . $file, 11);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?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\Persistence;
|
||||
|
||||
use Exception;
|
||||
use PrivateBin\Json;
|
||||
|
||||
/**
|
||||
* DataStore
|
||||
*
|
||||
* Handles data storage for Data\Filesystem.
|
||||
*/
|
||||
class DataStore extends AbstractPersistence
|
||||
{
|
||||
/**
|
||||
* store the data
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $filename
|
||||
* @param array $data
|
||||
* @return bool
|
||||
*/
|
||||
public static function store($filename, $data)
|
||||
{
|
||||
$path = self::getPath();
|
||||
if (strpos($filename, $path) === 0) {
|
||||
$filename = substr($filename, strlen($path));
|
||||
}
|
||||
try {
|
||||
self::_store($filename, Json::encode($data));
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,7 +36,6 @@ class PurgeLimiter extends AbstractPersistence
|
|||
* @access public
|
||||
* @static
|
||||
* @param int $limit
|
||||
* @return void
|
||||
*/
|
||||
public static function setLimit($limit)
|
||||
{
|
||||
|
@ -49,7 +48,6 @@ class PurgeLimiter extends AbstractPersistence
|
|||
* @access public
|
||||
* @static
|
||||
* @param Configuration $conf
|
||||
* @return void
|
||||
*/
|
||||
public static function setConfiguration(Configuration $conf)
|
||||
{
|
||||
|
|
|
@ -95,7 +95,6 @@ class ServerSalt extends AbstractPersistence
|
|||
* @access public
|
||||
* @static
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public static function setPath($path)
|
||||
{
|
||||
|
|
|
@ -45,7 +45,6 @@ class TrafficLimiter extends AbstractPersistence
|
|||
* @access public
|
||||
* @static
|
||||
* @param int $limit
|
||||
* @return void
|
||||
*/
|
||||
public static function setLimit($limit)
|
||||
{
|
||||
|
@ -58,7 +57,6 @@ class TrafficLimiter extends AbstractPersistence
|
|||
* @access public
|
||||
* @static
|
||||
* @param Configuration $conf
|
||||
* @return void
|
||||
*/
|
||||
public static function setConfiguration(Configuration $conf)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,13 @@ class PrivateBin
|
|||
*/
|
||||
const VERSION = '1.1';
|
||||
|
||||
/**
|
||||
* minimal required PHP version
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
const MIN_PHP_VERSION = '5.4.0';
|
||||
|
||||
/**
|
||||
* show the same error message if the paste expired or does not exist
|
||||
*
|
||||
|
@ -116,12 +123,11 @@ class PrivateBin
|
|||
*
|
||||
* @access public
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0') < 0) {
|
||||
throw new Exception(I18n::_('%s requires php 5.3.0 or above to work. Sorry.', I18n::_('PrivateBin')), 1);
|
||||
if (version_compare(PHP_VERSION, self::MIN_PHP_VERSION) < 0) {
|
||||
throw new Exception(I18n::_('%s requires php %s or above to work. Sorry.', I18n::_('PrivateBin'), self::MIN_PHP_VERSION), 1);
|
||||
}
|
||||
if (strlen(PATH) < 0 && substr(PATH, -1) !== DIRECTORY_SEPARATOR) {
|
||||
throw new Exception(I18n::_('%s requires the PATH to end in a "%s". Please update the PATH in your index.php.', I18n::_('PrivateBin'), DIRECTORY_SEPARATOR), 5);
|
||||
|
@ -164,21 +170,9 @@ class PrivateBin
|
|||
* initialize privatebin
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function _init()
|
||||
{
|
||||
foreach (array('cfg', 'lib') as $dir) {
|
||||
if (!is_file(PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess')) {
|
||||
file_put_contents(
|
||||
PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess',
|
||||
'Allow from none' . PHP_EOL .
|
||||
'Deny from all' . PHP_EOL,
|
||||
LOCK_EX
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_conf = new Configuration;
|
||||
$this->_model = new Model($this->_conf);
|
||||
$this->_request = new Request;
|
||||
|
@ -324,7 +318,6 @@ class PrivateBin
|
|||
* @access private
|
||||
* @param string $dataid
|
||||
* @param string $deletetoken
|
||||
* @return void
|
||||
*/
|
||||
private function _delete($dataid, $deletetoken)
|
||||
{
|
||||
|
@ -334,19 +327,16 @@ class PrivateBin
|
|||
// accessing this property ensures that the paste would be
|
||||
// deleted if it has already expired
|
||||
$burnafterreading = $paste->isBurnafterreading();
|
||||
if ($deletetoken == 'burnafterreading') {
|
||||
if ($burnafterreading) {
|
||||
$paste->delete();
|
||||
$this->_return_message(0, $dataid);
|
||||
} else {
|
||||
$this->_return_message(1, 'Paste is not of burn-after-reading type.');
|
||||
}
|
||||
} else {
|
||||
// Make sure the token is valid.
|
||||
if (Filter::slowEquals($deletetoken, $paste->getDeleteToken())) {
|
||||
if (
|
||||
($burnafterreading && $deletetoken == 'burnafterreading') ||
|
||||
Filter::slowEquals($deletetoken, $paste->getDeleteToken())
|
||||
) {
|
||||
// Paste exists and deletion token is valid: Delete the paste.
|
||||
$paste->delete();
|
||||
$this->_status = 'Paste was properly deleted.';
|
||||
} else {
|
||||
if (!$burnafterreading && $deletetoken == 'burnafterreading') {
|
||||
$this->_error = 'Paste is not of burn-after-reading type.';
|
||||
} else {
|
||||
$this->_error = 'Wrong deletion token. Paste was not deleted.';
|
||||
}
|
||||
|
@ -357,6 +347,13 @@ class PrivateBin
|
|||
} catch (Exception $e) {
|
||||
$this->_error = $e->getMessage();
|
||||
}
|
||||
if ($this->_request->isJsonApiCall()) {
|
||||
if (strlen($this->_error)) {
|
||||
$this->_return_message(1, $this->_error);
|
||||
} else {
|
||||
$this->_return_message(0, $dataid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -364,7 +361,6 @@ class PrivateBin
|
|||
*
|
||||
* @access private
|
||||
* @param string $dataid
|
||||
* @return void
|
||||
*/
|
||||
private function _read($dataid)
|
||||
{
|
||||
|
@ -397,7 +393,6 @@ class PrivateBin
|
|||
* Display PrivateBin frontend.
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function _view()
|
||||
{
|
||||
|
@ -461,7 +456,6 @@ class PrivateBin
|
|||
*
|
||||
* @access private
|
||||
* @param string $type
|
||||
* @return void
|
||||
*/
|
||||
private function _jsonld($type)
|
||||
{
|
||||
|
@ -494,7 +488,6 @@ class PrivateBin
|
|||
* @param int $status
|
||||
* @param string $message
|
||||
* @param array $other
|
||||
* @return void
|
||||
*/
|
||||
private function _return_message($status, $message, $other = array())
|
||||
{
|
||||
|
|
|
@ -41,7 +41,7 @@ class Request
|
|||
const MIME_XHTML = 'application/xhtml+xml';
|
||||
|
||||
/**
|
||||
* Input stream to use for PUT parameter parsing.
|
||||
* Input stream to use for PUT parameter parsing
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
|
@ -49,7 +49,7 @@ class Request
|
|||
private static $_inputStream = 'php://input';
|
||||
|
||||
/**
|
||||
* Operation to perform.
|
||||
* Operation to perform
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
|
@ -57,7 +57,7 @@ class Request
|
|||
private $_operation = 'view';
|
||||
|
||||
/**
|
||||
* Request parameters.
|
||||
* Request parameters
|
||||
*
|
||||
* @access private
|
||||
* @var array
|
||||
|
@ -65,7 +65,7 @@ class Request
|
|||
private $_params = array();
|
||||
|
||||
/**
|
||||
* If we are in a JSON API context.
|
||||
* If we are in a JSON API context
|
||||
*
|
||||
* @access private
|
||||
* @var bool
|
||||
|
@ -73,20 +73,12 @@ class Request
|
|||
private $_isJsonApi = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// in case stupid admin has left magic_quotes enabled in php.ini (for PHP < 5.4)
|
||||
if (version_compare(PHP_VERSION, '5.4.0') < 0 && get_magic_quotes_gpc()) {
|
||||
$_POST = array_map('PrivateBin\\Filter::stripslashesDeep', $_POST);
|
||||
$_GET = array_map('PrivateBin\\Filter::stripslashesDeep', $_GET);
|
||||
$_COOKIE = array_map('PrivateBin\\Filter::stripslashesDeep', $_COOKIE);
|
||||
}
|
||||
|
||||
// decide if we are in JSON API or HTML context
|
||||
$this->_isJsonApi = $this->_detectJsonRequest();
|
||||
|
||||
|
@ -129,7 +121,7 @@ class Request
|
|||
}
|
||||
|
||||
/**
|
||||
* Get current operation.
|
||||
* Get current operation
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
|
@ -140,7 +132,7 @@ class Request
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a request parameter.
|
||||
* Get a request parameter
|
||||
*
|
||||
* @access public
|
||||
* @param string $param
|
||||
|
@ -153,7 +145,7 @@ class Request
|
|||
}
|
||||
|
||||
/**
|
||||
* If we are in a JSON API context.
|
||||
* If we are in a JSON API context
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
|
@ -164,7 +156,7 @@ class Request
|
|||
}
|
||||
|
||||
/**
|
||||
* Override the default input stream source, used for unit testing.
|
||||
* Override the default input stream source, used for unit testing
|
||||
*
|
||||
* @param string $input
|
||||
*/
|
||||
|
@ -174,7 +166,7 @@ class Request
|
|||
}
|
||||
|
||||
/**
|
||||
* detect the clients supported media type and decide if its a JSON API call or not
|
||||
* Detect the clients supported media type and decide if its a JSON API call or not
|
||||
*
|
||||
* Adapted from: https://stackoverflow.com/questions/3770513/detect-browser-language-in-php#3771447
|
||||
*
|
||||
|
|
|
@ -35,7 +35,6 @@ class View
|
|||
* @access public
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function assign($name, $value)
|
||||
{
|
||||
|
@ -48,7 +47,6 @@ class View
|
|||
* @access public
|
||||
* @param string $template
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function draw($template)
|
||||
{
|
||||
|
|
|
@ -61,7 +61,6 @@ class Vizhash16x16
|
|||
* constructor
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -210,7 +209,6 @@ class Vizhash16x16
|
|||
* @param resource $image
|
||||
* @param int $action
|
||||
* @param int $color
|
||||
* @return void
|
||||
*/
|
||||
private function drawshape($image, $action, $color)
|
||||
{
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Require all denied
|
|
@ -4,7 +4,7 @@ $isCpct = substr($template, 9, 8) === '-compact';
|
|||
$isDark = substr($template, 9, 5) === '-dark';
|
||||
$isPage = substr($template, -5) === '-page';
|
||||
?><!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
@ -69,7 +69,7 @@ if ($MARKDOWN):
|
|||
<?php
|
||||
endif;
|
||||
?>
|
||||
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-/5orRNmbpvxqudg675a1LiF3wQ5DlMGoT6jI/iXDZN2x2DrLHnB3tSE0wGY6qpeY+eX9vv6mZ/6AuPm0gnU2/A==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-+/yhR0jcxCRLS10m+w8ii0BDeifeMrT7moI3gNalod6rHdgzMfc962q+2q3880fQ5XhcjF+/hx+8bKxRUMOaCg==" crossorigin="anonymous"></script>
|
||||
<!--[if lt IE 10]>
|
||||
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
||||
<![endif]-->
|
||||
|
@ -94,7 +94,7 @@ endif;
|
|||
<form id="passwordform" role="form">
|
||||
<div class="form-group">
|
||||
<label for="passworddecrypt"><span class="glyphicon glyphicon-eye-open"></span> <?php echo I18n::_('Please enter the password for this paste:') ?></label>
|
||||
<input id="passworddecrypt" type="password" class="form-control" placeholder="<?php echo I18n::_('Enter password') ?>" autofocus>
|
||||
<input id="passworddecrypt" type="password" class="form-control" placeholder="<?php echo I18n::_('Enter password') ?>">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success btn-block"><span class="glyphicon glyphicon-off"></span> <?php echo I18n::_('Decrypt') ?></button>
|
||||
</form>
|
||||
|
@ -121,8 +121,8 @@ endif;
|
|||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li id="loadingindicator" class="navbar-text hidden">
|
||||
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('Uploading paste… Please wait.'), PHP_EOL; ?>
|
||||
<span class="glyphicon glyphicon-time" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('Loading…'), PHP_EOL; ?>
|
||||
</li>
|
||||
<li>
|
||||
<?php
|
||||
|
@ -132,7 +132,7 @@ if ($isPage):
|
|||
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL;
|
||||
else:
|
||||
?>
|
||||
<button id="newbutton" type="button" class="reloadlink hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
|
||||
<button id="newbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
|
||||
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL;
|
||||
endif;
|
||||
?>
|
||||
|
@ -198,7 +198,7 @@ if ($isCpct):
|
|||
<?php
|
||||
if ($DISCUSSION):
|
||||
?>
|
||||
<li id="opendisc" class="checkbox hidden">
|
||||
<li id="opendiscussionoption" class="checkbox hidden">
|
||||
<label>
|
||||
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
|
||||
if ($OPENDISCUSSION):
|
||||
|
@ -230,17 +230,6 @@ if ($isCpct):
|
|||
?>
|
||||
</ul>
|
||||
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
|
||||
<?php
|
||||
foreach ($FORMATTER as $key => $value):
|
||||
?>
|
||||
<option value="<?php echo $key; ?>"<?php
|
||||
if ($key == $FORMATTERDEFAULT):
|
||||
?> selected="selected"<?php
|
||||
endif;
|
||||
?>><?php echo $value; ?></option>
|
||||
<?php
|
||||
endforeach;
|
||||
?>
|
||||
</select>
|
||||
</li>
|
||||
<?php
|
||||
|
@ -262,7 +251,7 @@ else:
|
|||
if ($DISCUSSION):
|
||||
?>
|
||||
<li>
|
||||
<div id="opendisc" class="navbar-text checkbox hidden">
|
||||
<div id="opendiscussionoption" class="navbar-text checkbox hidden">
|
||||
<label>
|
||||
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
|
||||
if ($OPENDISCUSSION):
|
||||
|
@ -296,6 +285,7 @@ if ($FILEUPLOAD):
|
|||
</div>
|
||||
<div id="dragAndDropFileName" class="dragAndDropFile"><?php echo I18n::_('or drag & drop file'); ?></div>
|
||||
</li>
|
||||
<li id="customattachment" class="hidden"></li>
|
||||
<li>
|
||||
<a id="fileremovebutton" href="#">
|
||||
<?php echo I18n::_('Remove attachment'), PHP_EOL; ?>
|
||||
|
@ -384,49 +374,57 @@ if ($isCpct):
|
|||
?></div><?php
|
||||
endif;
|
||||
?></nav>
|
||||
<header class="container">
|
||||
<main>
|
||||
<section class="container">
|
||||
<?php
|
||||
if (strlen($NOTICE)):
|
||||
?>
|
||||
<div role="alert" class="alert alert-info">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <?php echo htmlspecialchars($NOTICE), PHP_EOL; ?>
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
|
||||
<?php echo htmlspecialchars($NOTICE), PHP_EOL; ?>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<div id="remainingtime" role="alert" class="hidden alert alert-info">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
|
||||
<span class="glyphicon glyphicon-fire" aria-hidden="true"></span>
|
||||
</div>
|
||||
<?php
|
||||
if ($FILEUPLOAD):
|
||||
?>
|
||||
<div id="attachment" role="alert" class="hidden alert alert-info">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a><?php echo I18n::_('Download attachment'); ?></a> <span id="clonedfile" class="hidden"><?php echo I18n::_('Cloned file attached.'); ?></span>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
if (strlen($STATUS)):
|
||||
?>
|
||||
<div id="status" role="alert" class="alert alert-success">
|
||||
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <?php echo htmlspecialchars($STATUS), PHP_EOL; ?>
|
||||
<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
|
||||
<a class="alert-link"><?php echo I18n::_('Download attachment'), PHP_EOL; ?></a>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<div id="errormessage" role="alert" class="<?php
|
||||
if (!strlen($ERROR)):
|
||||
?>hidden <?php
|
||||
endif;
|
||||
?>alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo htmlspecialchars($ERROR); ?></div>
|
||||
<noscript><div id="noscript" role="alert" class="nonworking alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <?php echo I18n::_('JavaScript is required for %s to work.<br />Sorry for the inconvenience.', I18n::_($NAME)); ?></div></noscript>
|
||||
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> <?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)); ?></div>
|
||||
<div id="ienotice" role="alert" class="hidden alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> <?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?>
|
||||
<div id="status" role="alert" class="statusmessage alert alert-info<?php echo empty($STATUS) ? ' hidden' : '' ?>">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
|
||||
<?php echo htmlspecialchars($STATUS), PHP_EOL; ?>
|
||||
</div>
|
||||
<div id="errormessage" role="alert" class="statusmessage<?php echo empty($ERROR) ? ' hidden' : '' ?> alert alert-danger">
|
||||
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
|
||||
<?php echo htmlspecialchars($ERROR), PHP_EOL; ?>
|
||||
</div>
|
||||
<noscript>
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('JavaScript is required for %s to work.<br />Sorry for the inconvenience.', I18n::_($NAME)), PHP_EOL; ?>
|
||||
</div>
|
||||
</noscript>
|
||||
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger">
|
||||
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?>
|
||||
</div>
|
||||
<div id="ienotice" role="alert" class="hidden alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
|
||||
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?>
|
||||
<a href="https://www.mozilla.org/firefox/">Firefox</a>,
|
||||
<a href="https://www.opera.com/">Opera</a>,
|
||||
<a href="https://www.google.com/chrome">Chrome</a>,
|
||||
<a href="https://www.apple.com/safari">Safari</a>...
|
||||
<a href="https://www.google.com/chrome">Chrome</a>…
|
||||
</div>
|
||||
<div id="pasteresult" role="alert" class="hidden alert alert-success">
|
||||
<div id="pasteSuccess" role="alert" class="hidden alert alert-success">
|
||||
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
|
||||
<div id="deletelink"></div>
|
||||
<div id="pastelink">
|
||||
|
@ -441,30 +439,32 @@ endif;
|
|||
?>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="preview" class="nav nav-tabs hidden">
|
||||
<ul id="editorTabs" class="nav nav-tabs hidden">
|
||||
<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
|
||||
<li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
|
||||
</ul>
|
||||
</header>
|
||||
</section>
|
||||
<section class="container">
|
||||
<article class="row">
|
||||
<div id="placeholder" class="col-md-12 hidden"><?php echo I18n::_('+++ no paste text +++'); ?></div>
|
||||
<div id="attachmentPreview" class="col-md-12 text-center hidden"></div>
|
||||
<div id="prettymessage" class="col-md-12 hidden">
|
||||
<pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre>
|
||||
</div>
|
||||
<div id="cleartext" class="col-md-12 hidden"></div>
|
||||
<div id="plaintext" class="col-md-12 hidden"></div>
|
||||
<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
|
||||
</article>
|
||||
</section>
|
||||
<section class="container">
|
||||
<div id="discussion" class="hidden">
|
||||
<h4><?php echo I18n::_('Discussion'); ?></h4>
|
||||
<div id="comments"></div>
|
||||
<div id="commentcontainer"></div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="container">
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">
|
||||
<span> <?php echo I18n::_('Loading…'); ?></span><br>
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide">
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||
<?php echo I18n::_('Loading…'); ?><br />
|
||||
<span class="small"><?php echo I18n::_('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>.'); ?></span>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -477,6 +477,21 @@ endif;
|
|||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="cipherdata" class="hidden"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div>
|
||||
</main>
|
||||
<div id="serverdata" class="hidden" aria-hidden="true">
|
||||
<div id="cipherdata"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div>
|
||||
<?php
|
||||
if ($DISCUSSION):
|
||||
?>
|
||||
<div id="templates">
|
||||
<!-- @TODO: when I intend/structure this corrrectly Firefox adds whitespaces everywhere which completly destroy the layout. (same possible when you remove the template data below and show this area in the browser) -->
|
||||
<article id="commenttemplate" class="comment"><div class="commentmeta"><span class="nickname">name</span><span class="commentdate">0000-00-00</span></div><div class="commentdata">c</div><button class="btn btn-default btn-sm"><?php echo I18n::_('Reply'); ?></button></article>
|
||||
<p id="commenttailtemplate" class="comment"><button class="btn btn-default btn-sm"><?php echo I18n::_('Add comment'); ?></button></p>
|
||||
<div id="replytemplate" class="reply hidden"><input type="text" id="nickname" class="form-control" title="<?php echo I18n::_('Optional nickname…'); ?>" placeholder="<?php echo I18n::_('Optional nickname…'); ?>" /><textarea id="replymessage" class="replymessage form-control" cols="80" rows="7"></textarea><br /><div id="replystatus" role="alert" class="statusmessage hidden alert"><span class="glyphicon" aria-hidden="true"></span> </div><button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button></div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
26
tpl/page.php
26
tpl/page.php
|
@ -47,7 +47,7 @@ if ($MARKDOWN):
|
|||
<?php
|
||||
endif;
|
||||
?>
|
||||
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-/5orRNmbpvxqudg675a1LiF3wQ5DlMGoT6jI/iXDZN2x2DrLHnB3tSE0wGY6qpeY+eX9vv6mZ/6AuPm0gnU2/A==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-+/yhR0jcxCRLS10m+w8ii0BDeifeMrT7moI3gNalod6rHdgzMfc962q+2q3880fQ5XhcjF+/hx+8bKxRUMOaCg==" crossorigin="anonymous"></script>
|
||||
<!--[if lt IE 10]>
|
||||
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
||||
<![endif]-->
|
||||
|
@ -79,12 +79,12 @@ endif;
|
|||
<div id="ienotice"><?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?>
|
||||
<a href="https://www.mozilla.org/firefox/">Firefox</a>,
|
||||
<a href="https://www.opera.com/">Opera</a>,
|
||||
<a href="https://www.google.com/chrome">Chrome</a>,
|
||||
<a href="https://www.apple.com/safari">Safari</a>...
|
||||
<a href="https://www.google.com/chrome">Chrome</a>…
|
||||
</div>
|
||||
</header>
|
||||
<section>
|
||||
<article>
|
||||
<div id="loadingindicator" class="hidden"><?php echo I18n::_('Loading…'); ?></div>
|
||||
<div id="status"><?php echo htmlspecialchars($STATUS); ?></div>
|
||||
<div id="errormessage" class="hidden"><?php echo htmlspecialchars($ERROR); ?></div>
|
||||
<div id="toolbar">
|
||||
|
@ -125,7 +125,7 @@ endif;
|
|||
<?php
|
||||
if ($DISCUSSION):
|
||||
?>
|
||||
<div id="opendisc" class="button hidden">
|
||||
<div id="opendiscussionoption" class="button hidden">
|
||||
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
|
||||
if ($OPENDISCUSSION):
|
||||
?> checked="checked"<?php
|
||||
|
@ -217,17 +217,31 @@ endif;
|
|||
<div id="prettymessage" class="hidden">
|
||||
<pre id="prettyprint" class="prettyprint linenums:1"></pre>
|
||||
</div>
|
||||
<div id="cleartext" class="hidden"></div>
|
||||
<div id="plaintext" class="hidden"></div>
|
||||
<textarea id="message" name="message" cols="80" rows="25" class="hidden"></textarea>
|
||||
</article>
|
||||
</section>
|
||||
<section>
|
||||
<div id="discussion" class="hidden">
|
||||
<h4 class="title"><?php echo I18n::_('Discussion'); ?></h4>
|
||||
<div id="comments"></div>
|
||||
<div id="commentcontainer"></div>
|
||||
</div>
|
||||
</section>
|
||||
<div id="serverdata" class="hidden" aria-hidden="true">
|
||||
<div id="cipherdata" class="hidden"><?php echo htmlspecialchars($CIPHERDATA, ENT_NOQUOTES); ?></div>
|
||||
<?php
|
||||
if ($DISCUSSION):
|
||||
?>
|
||||
<div id="templates">
|
||||
<!-- @TODO: when I intend/structure this corrrectly Firefox adds whitespaces everywhere which completly destroy the layout. (same possible when you remove the template data below and show this area in the browser) -->
|
||||
<article id="commenttemplate" class="comment"><div class="commentmeta"><span class="nickname">name</span><span class="commentdate">0000-00-00</span></div><div class="commentdata">c</div><button class="btn btn-default btn-sm"><?php echo I18n::_('Reply'); ?></button></article>
|
||||
<div id="commenttailtemplate" class="comment"><button class="btn btn-default btn-sm"><?php echo I18n::_('Add comment'); ?></button></div>
|
||||
<div id="replytemplate" class="reply hidden"><input type="text" id="nickname" class="form-control" title="<?php echo I18n::_('Optional nickname…'); ?>" placeholder="<?php echo I18n::_('Optional nickname…'); ?>" /><textarea id="replymessage" class="replymessage form-control" cols="80" rows="7"></textarea><br /><div id="replystatus" role="alert" class="statusmessage hidden alert"><span class="glyphicon" aria-hidden="true"></span> </div><button id="replybutton" class="btn btn-default btn-sm"><?php echo I18n::_('Post comment'); ?></button></div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
</div>
|
||||
<section class="container">
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">
|
||||
<span> <?php echo I18n::_('Loading…'); ?></span><br>
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/ConfigurationCombinationsTest.php
|
|
@ -1,2 +0,0 @@
|
|||
Allow from none
|
||||
Deny from all
|
|
@ -172,6 +172,7 @@ class Helper
|
|||
*/
|
||||
public static function rmDir($path)
|
||||
{
|
||||
if (is_dir($path)) {
|
||||
$path .= DIRECTORY_SEPARATOR;
|
||||
$dir = dir($path);
|
||||
while (false !== ($file = $dir->read())) {
|
||||
|
@ -190,6 +191,7 @@ class Helper
|
|||
throw new Exception('Error deleting directory "' . $path . '".');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a backup of the config file
|
||||
|
|
|
@ -311,7 +311,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
|
|||
'vizhash BLOB, ' .
|
||||
'postdate INT );'
|
||||
);
|
||||
$this->assertInstanceOf(Database::class, Database::getInstance($this->_options));
|
||||
$this->assertInstanceOf('PrivateBin\\Data\\Database', Database::getInstance($this->_options));
|
||||
|
||||
// check if version number was upgraded in created configuration table
|
||||
$statement = $db->prepare('SELECT value FROM foo_config WHERE id LIKE ?');
|
||||
|
|
|
@ -8,16 +8,26 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
|
|||
|
||||
private $_path;
|
||||
|
||||
private $_invalidPath;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
/* Setup Routine */
|
||||
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
|
||||
$this->_invalidPath = $this->_path . DIRECTORY_SEPARATOR . 'bar';
|
||||
$this->_model = Filesystem::getInstance(array('dir' => $this->_path));
|
||||
if (!is_dir($this->_path)) {
|
||||
mkdir($this->_path);
|
||||
}
|
||||
if (!is_dir($this->_invalidPath)) {
|
||||
mkdir($this->_invalidPath);
|
||||
}
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
/* Tear Down Routine */
|
||||
chmod($this->_invalidPath, 0700);
|
||||
Helper::rmDir($this->_path);
|
||||
}
|
||||
|
||||
|
@ -37,6 +47,7 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
|
|||
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does not yet exist');
|
||||
$this->assertTrue($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()), 'store comment');
|
||||
$this->assertTrue($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment exists after storing it');
|
||||
$this->assertFalse($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()), 'unable to store the same comment twice');
|
||||
$comment = json_decode(json_encode(Helper::getComment()));
|
||||
$comment->id = Helper::getCommentId();
|
||||
$comment->parentid = Helper::getPasteId();
|
||||
|
@ -99,10 +110,6 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionCode 90
|
||||
*/
|
||||
public function testErrorDetection()
|
||||
{
|
||||
$this->_model->delete(Helper::getPasteId());
|
||||
|
@ -112,10 +119,6 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
|
|||
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does still not exist');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionCode 90
|
||||
*/
|
||||
public function testCommentErrorDetection()
|
||||
{
|
||||
$this->_model->delete(Helper::getPasteId());
|
||||
|
|
|
@ -4,14 +4,6 @@ use PrivateBin\Filter;
|
|||
|
||||
class FilterTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testFilterStripsSlashesDeeply()
|
||||
{
|
||||
$this->assertEquals(
|
||||
array("f'oo", "b'ar", array("fo'o", "b'ar")),
|
||||
Filter::stripslashesDeep(array("f\\'oo", "b\\'ar", array("fo\\'o", "b\\'ar")))
|
||||
);
|
||||
}
|
||||
|
||||
public function testFilterMakesTimesHumanlyReadable()
|
||||
{
|
||||
$this->assertEquals('5 minutes', Filter::formatHumanReadableTime('5min'));
|
||||
|
|
|
@ -142,4 +142,36 @@ class I18nTest extends PHPUnit_Framework_TestCase
|
|||
I18n::loadTranslations();
|
||||
$this->assertEquals('some string + 1', I18n::_('some %s + %d', 'string', 1), 'browser language en');
|
||||
}
|
||||
|
||||
public function testMessageIdsExistInAllLanguages()
|
||||
{
|
||||
$messageIds = array();
|
||||
$languages = array();
|
||||
$dir = dir(PATH . 'i18n');
|
||||
while (false !== ($file = $dir->read())) {
|
||||
if (strlen($file) === 7) {
|
||||
$language = substr($file, 0, 2);
|
||||
$languageMessageIds = array_keys(
|
||||
json_decode(
|
||||
file_get_contents(PATH . 'i18n' . DIRECTORY_SEPARATOR . $file),
|
||||
true
|
||||
)
|
||||
);
|
||||
$messageIds = array_unique(array_merge($messageIds, $languageMessageIds));
|
||||
$languages[$language] = $languageMessageIds;
|
||||
}
|
||||
}
|
||||
foreach ($messageIds as $messageId) {
|
||||
foreach (array_keys($languages) as $language) {
|
||||
// most languages don't translate the data size units, ignore those
|
||||
if ($messageId !== 'B' && strlen($messageId) !== 3 && strpos($messageId, 'B', 2) !== 2) {
|
||||
$this->assertContains(
|
||||
$messageId,
|
||||
$languages[$language],
|
||||
"message ID '$messageId' exists in translation file $language.json"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
|
|||
new PrivateBin;
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
unlink($file);
|
||||
$response = json_decode($content, true);
|
||||
$this->assertEquals(0, $response['status'], 'outputs status');
|
||||
$this->assertEquals(Helper::getPasteId(), $response['id'], 'outputted paste ID matches input');
|
||||
|
@ -132,6 +133,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
|
|||
new PrivateBin;
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
unlink($file);
|
||||
$response = json_decode($content, true);
|
||||
$this->assertEquals(0, $response['status'], 'outputs status');
|
||||
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
|
||||
|
@ -147,10 +149,9 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
|
|||
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
|
||||
$paste = $this->_model->read(Helper::getPasteId());
|
||||
$_POST = array(
|
||||
'action' => 'delete',
|
||||
'pasteid' => Helper::getPasteId(),
|
||||
'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste->meta->salt),
|
||||
);
|
||||
$_SERVER['QUERY_STRING'] = Helper::getPasteId();
|
||||
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
|
||||
$_SERVER['REQUEST_METHOD'] = 'POST';
|
||||
ob_start();
|
||||
|
|
|
@ -82,6 +82,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
|
|||
$comment = $paste->getComment(Helper::getPasteId());
|
||||
$comment->setData($commentData['data']);
|
||||
$comment->setNickname($commentData['meta']['nickname']);
|
||||
$comment->getParentId();
|
||||
$comment->store();
|
||||
|
||||
$comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
|
||||
|
@ -189,6 +190,27 @@ class ModelTest extends PHPUnit_Framework_TestCase
|
|||
$this->assertFalse(Paste::isValidId('../bar/baz'), 'path attack');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionCode 64
|
||||
*/
|
||||
public function testInvalidPaste()
|
||||
{
|
||||
$this->_model->getPaste(Helper::getPasteId())->delete();
|
||||
$paste = $this->_model->getPaste(Helper::getPasteId());
|
||||
$paste->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionCode 61
|
||||
*/
|
||||
public function testInvalidData()
|
||||
{
|
||||
$paste = $this->_model->getPaste();
|
||||
$paste->setData('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionCode 62
|
||||
|
@ -199,6 +221,37 @@ class ModelTest extends PHPUnit_Framework_TestCase
|
|||
$paste->getComment(Helper::getPasteId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionCode 67
|
||||
*/
|
||||
public function testInvalidCommentDeletedPaste()
|
||||
{
|
||||
$pasteData = Helper::getPaste();
|
||||
$paste = $this->_model->getPaste(Helper::getPasteId());
|
||||
$paste->setData($pasteData['data']);
|
||||
$paste->store();
|
||||
|
||||
$comment = $paste->getComment(Helper::getPasteId());
|
||||
$paste->delete();
|
||||
$comment->store();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionCode 68
|
||||
*/
|
||||
public function testInvalidCommentData()
|
||||
{
|
||||
$pasteData = Helper::getPaste();
|
||||
$paste = $this->_model->getPaste(Helper::getPasteId());
|
||||
$paste->setData($pasteData['data']);
|
||||
$paste->store();
|
||||
|
||||
$comment = $paste->getComment(Helper::getPasteId());
|
||||
$comment->store();
|
||||
}
|
||||
|
||||
public function testExpiration()
|
||||
{
|
||||
$pasteData = Helper::getPaste();
|
||||
|
|
|
@ -140,21 +140,18 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
public function testHtaccess()
|
||||
{
|
||||
$this->reset();
|
||||
$dirs = array('cfg', 'lib');
|
||||
foreach ($dirs as $dir) {
|
||||
$file = PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess';
|
||||
$file = $this->_path . DIRECTORY_SEPARATOR . '.htaccess';
|
||||
@unlink($file);
|
||||
}
|
||||
|
||||
$_POST = Helper::getPaste();
|
||||
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
|
||||
$_SERVER['REQUEST_METHOD'] = 'POST';
|
||||
$_SERVER['REMOTE_ADDR'] = '::1';
|
||||
ob_start();
|
||||
new PrivateBin;
|
||||
ob_end_clean();
|
||||
foreach ($dirs as $dir) {
|
||||
$file = PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess';
|
||||
$this->assertFileExists(
|
||||
$file,
|
||||
"$dir htaccess recreated"
|
||||
);
|
||||
}
|
||||
|
||||
$this->assertFileExists($file, 'htaccess recreated');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -739,10 +736,10 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
new PrivateBin;
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertContains(
|
||||
'<div id="cipherdata" class="hidden">' .
|
||||
htmlspecialchars(Helper::getPasteAsJson(), ENT_NOQUOTES) .
|
||||
'</div>',
|
||||
$this->assertRegExp(
|
||||
'#<div id="cipherdata"[^>]*>' .
|
||||
preg_quote(htmlspecialchars(Helper::getPasteAsJson(), ENT_NOQUOTES)) .
|
||||
'</div>#',
|
||||
$content,
|
||||
'outputs data correctly'
|
||||
);
|
||||
|
@ -760,7 +757,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Invalid paste ID\.</div>#',
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Invalid paste ID\.#s',
|
||||
$content,
|
||||
'outputs error correctly'
|
||||
);
|
||||
|
@ -778,7 +775,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist[^<]*</div>#',
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist, has expired or has been deleted\.#s',
|
||||
$content,
|
||||
'outputs error correctly'
|
||||
);
|
||||
|
@ -798,7 +795,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist[^<]*</div>#',
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist, has expired or has been deleted\.#s',
|
||||
$content,
|
||||
'outputs error correctly'
|
||||
);
|
||||
|
@ -818,10 +815,10 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
unset($burnPaste['meta']['salt']);
|
||||
$this->assertContains(
|
||||
'<div id="cipherdata" class="hidden">' .
|
||||
htmlspecialchars(Helper::getPasteAsJson($burnPaste['meta']), ENT_NOQUOTES) .
|
||||
'</div>',
|
||||
$this->assertRegExp(
|
||||
'#<div id="cipherdata"[^>]*>' .
|
||||
preg_quote(htmlspecialchars(Helper::getPasteAsJson($burnPaste['meta']), ENT_NOQUOTES)) .
|
||||
'</div>#',
|
||||
$content,
|
||||
'outputs data correctly'
|
||||
);
|
||||
|
@ -889,10 +886,10 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$meta['formatter'] = 'syntaxhighlighting';
|
||||
$this->assertContains(
|
||||
'<div id="cipherdata" class="hidden">' .
|
||||
htmlspecialchars(Helper::getPasteAsJson($meta), ENT_NOQUOTES) .
|
||||
'</div>',
|
||||
$this->assertRegExp(
|
||||
'#<div id="cipherdata"[^>]*>' .
|
||||
preg_quote(htmlspecialchars(Helper::getPasteAsJson($meta), ENT_NOQUOTES)) .
|
||||
'</div>#',
|
||||
$content,
|
||||
'outputs data correctly'
|
||||
);
|
||||
|
@ -914,10 +911,10 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
ob_end_clean();
|
||||
$oldPaste['meta']['formatter'] = 'plaintext';
|
||||
unset($oldPaste['meta']['salt']);
|
||||
$this->assertContains(
|
||||
'<div id="cipherdata" class="hidden">' .
|
||||
htmlspecialchars(Helper::getPasteAsJson($oldPaste['meta']), ENT_NOQUOTES) .
|
||||
'</div>',
|
||||
$this->assertRegExp(
|
||||
'#<div id="cipherdata"[^>]*>' .
|
||||
preg_quote(htmlspecialchars(Helper::getPasteAsJson($oldPaste['meta']), ENT_NOQUOTES)) .
|
||||
'</div>#',
|
||||
$content,
|
||||
'outputs data correctly'
|
||||
);
|
||||
|
@ -939,7 +936,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]*id="status"[^>]*>.*Paste was properly deleted[^<]*</div>#s',
|
||||
'#<div[^>]*id="status"[^>]*>.*Paste was properly deleted\.#s',
|
||||
$content,
|
||||
'outputs deleted status correctly'
|
||||
);
|
||||
|
@ -960,7 +957,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Invalid paste ID\.</div>#',
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Invalid paste ID\.#s',
|
||||
$content,
|
||||
'outputs delete error correctly'
|
||||
);
|
||||
|
@ -980,7 +977,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist[^<]*</div>#',
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist, has expired or has been deleted\.#s',
|
||||
$content,
|
||||
'outputs delete error correctly'
|
||||
);
|
||||
|
@ -1000,7 +997,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Wrong deletion token[^<]*</div>#',
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Wrong deletion token\. Paste was not deleted\.#s',
|
||||
$content,
|
||||
'outputs delete error correctly'
|
||||
);
|
||||
|
@ -1047,7 +1044,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
ob_end_clean();
|
||||
$response = json_decode($content, true);
|
||||
$this->assertEquals(1, $response['status'], 'outputs status');
|
||||
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
|
||||
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after failing to delete data');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1067,7 +1064,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist[^<]*</div>#',
|
||||
'#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist, has expired or has been deleted\.#s',
|
||||
$content,
|
||||
'outputs error correctly'
|
||||
);
|
||||
|
@ -1091,7 +1088,7 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
|
|||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]*id="status"[^>]*>.*Paste was properly deleted[^<]*</div>#s',
|
||||
'#<div[^>]*id="status"[^>]*>.*Paste was properly deleted\.#s',
|
||||
$content,
|
||||
'outputs deleted status correctly'
|
||||
);
|
||||
|
|
|
@ -63,6 +63,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
|
|||
file_put_contents($file, 'data=foo');
|
||||
Request::setInputStream($file);
|
||||
$request = new Request;
|
||||
unlink($file);
|
||||
$this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
|
||||
$this->assertEquals('create', $request->getOperation());
|
||||
$this->assertEquals('foo', $request->getParam('data'));
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<?php
|
||||
|
||||
use PrivateBin\Persistence\ServerSalt;
|
||||
use PrivateBin\Sjcl;
|
||||
|
||||
class SjclTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSjclValidatorValidatesCorrectly()
|
||||
{
|
||||
ServerSalt::setPath(sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data');
|
||||
$paste = Helper::getPasteWithAttachment();
|
||||
$this->assertTrue(Sjcl::isValid($paste['data']), 'valid sjcl');
|
||||
$this->assertTrue(Sjcl::isValid($paste['attachment']), 'valid sjcl');
|
||||
|
|
|
@ -96,15 +96,15 @@ class ViewTest extends PHPUnit_Framework_TestCase
|
|||
public function testTemplateRendersCorrectly()
|
||||
{
|
||||
foreach ($this->_content as $template => $content) {
|
||||
$this->assertContains(
|
||||
'<div id="cipherdata" class="hidden">' .
|
||||
htmlspecialchars(Helper::getPaste()['data'], ENT_NOQUOTES) .
|
||||
'</div>',
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]+id="cipherdata"[^>]*>' .
|
||||
preg_quote(htmlspecialchars(Helper::getPaste()['data'], ENT_NOQUOTES)) .
|
||||
'</div>#',
|
||||
$content,
|
||||
$template . ': outputs data correctly'
|
||||
);
|
||||
$this->assertRegExp(
|
||||
'#<div[^>]+id="errormessage"[^>]*>.*' . self::$error . '</div>#',
|
||||
'#<div[^>]+id="errormessage"[^>]*>.*' . self::$error . '#s',
|
||||
$content,
|
||||
$template . ': outputs error correctly'
|
||||
);
|
||||
|
@ -119,7 +119,7 @@ class ViewTest extends PHPUnit_Framework_TestCase
|
|||
$template . ': checked discussion if configured'
|
||||
);
|
||||
$this->assertRegExp(
|
||||
'#<[^>]+id="opendisc"[^>]*>#',
|
||||
'#<[^>]+id="opendiscussionoption"[^>]*>#',
|
||||
$content,
|
||||
$template . ': discussions available if configured'
|
||||
);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Require all denied
|
Loading…
Reference in New Issue