Merge remote-tracking branch 'PrivateBin/master' into Italian-Translation

This commit is contained in:
Stefano Martinelli 2017-03-25 14:21:02 +01:00
commit 2ffc42eb8d
47 changed files with 627 additions and 320 deletions

1
.gitignore vendored
View file

@ -31,6 +31,7 @@ vendor/**/build_phar.php
# Ignore local node modules, unit testing logs, api docs and eclipse project files # Ignore local node modules, unit testing logs, api docs and eclipse project files
js/node_modules/ js/node_modules/
tst/log/ tst/log/
tst/ConfigurationCombinationsTest.php
.settings .settings
.buildpath .buildpath
.project .project

View file

@ -1,15 +1,26 @@
language: php language: php
sudo: false sudo: false
php: php:
- 5.5 - '5.4'
- 5.6 - '5.5'
- 7.0 - '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: before_script:
- composer install -n - composer install -n
- npm install -g mocha
- cd js
- npm install jsverify jsdom jsdom-global
- cd ..
script: script:
- cd tst && ../vendor/bin/phpunit - cd tst && ../vendor/bin/phpunit
- cd ../js && mocha
after_script: after_script:
- cd .. - cd ..

View file

@ -10,7 +10,7 @@ check the options and adjust them as you see fit.
### Requirements ### Requirements
- PHP version 5.3 or above - PHP version 5.4 or above
- _one_ of the following sources of cryptographically safe randomness is required: - _one_ of the following sources of cryptographically safe randomness is required:
- PHP 7 or higher - 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) - [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)

View file

@ -18,7 +18,7 @@
} }
], ],
"require": { "require": {
"php": "^5.3.0 || ^7.0", "php": "^5.4.0 || ^7.0",
"paragonie/random_compat": "2.0.4", "paragonie/random_compat": "2.0.4",
"yzalis/identicon": "1.1.0" "yzalis/identicon": "1.1.0"
}, },

View file

@ -7,8 +7,8 @@
"en": "de", "en": "de",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Diesen Text gibt es nicht, er ist abgelaufen oder wurde gelöscht.", "Diesen Text gibt es nicht, er ist abgelaufen oder wurde gelöscht.",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"%s benötigt PHP 5.3.0 oder höher, um zu funktionieren. 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 requires configuration section [%s] to be present in configuration file.":
"%s benötigt den Konfigurationsabschnitt [%s] in der Konfigurationsdatei um zu funktionieren.", "%s benötigt den Konfigurationsabschnitt [%s] in der Konfigurationsdatei um zu funktionieren.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -151,6 +151,5 @@
"Preparing new paste…": "Bereite neues Paste vor…", "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>.": "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 +++": "+++ no paste text +++": "+++ kein Paste-Text +++"
"+++ kein Paste-Text +++"
} }

View file

@ -7,8 +7,8 @@
"en": "es", "en": "es",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"El texto no existe, ha caducado o ha sido eliminado.", "El texto no existe, ha caducado o ha sido eliminado.",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"%s requiere php 5.3.0 o superior para funcionar. Lo siento.", "%s requiere php %s o superior para funcionar. Lo siento.",
"%s requires configuration section [%s] to be present in configuration file.": "%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.": "Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Responder", "Responder",
"Anonymous": "Anonymous":
"Anónimo", "Anónimo",
"Anonymous avatar (Vizhash of the IP address)": "Avatar generated from IP address":
"Avatar anónimo (Vizhash de la dirección IP)", "Avatar anónimo (Vizhash de la dirección IP)",
"Add comment": "Add comment":
"Añadir comentario", "Añadir comentario",
@ -112,8 +112,8 @@
"Error del servidor o el servidor no responde", "Error del servidor o el servidor no responde",
"Could not post comment: %s": "Could not post comment: %s":
"No fue posible publicar comentario: %s", "No fue posible publicar comentario: %s",
"Sending paste (Please move your mouse for more entropy)…": "Please move your mouse for more entropy…":
"Enviando texto (Por favor, mueva el ratón para mayor entropía)…", "Por favor, mueva el ratón para mayor entropía…",
"Sending paste…": "Sending paste…":
"Enviando texto…", "Enviando texto…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -129,7 +129,8 @@
"Source Code": "Código fuente", "Source Code": "Código fuente",
"Markdown": "Markdown", "Markdown": "Markdown",
"Download attachment": "Descargar adjunto", "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", "Attach a file": "Adjuntar archivo",
"Remove attachment": "Remover adjunto", "Remove attachment": "Remover adjunto",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password": "Enter password":
"Ingrese contraseña", "Ingrese contraseña",
"Loading…": "Cargando…", "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>.": "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 +++"
} }

View file

@ -7,8 +7,8 @@
"en": "fr", "en": "fr",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Le paste n'existe pas, a expiré, ou a été supprimé.", "Le paste n'existe pas, a expiré, ou a été supprimé.",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"Désolé, %s nécessite php 5.3.0 ou supérieur pour fonctionner.", "Désolé, %s nécessite php %s ou supérieur pour fonctionner.",
"%s requires configuration section [%s] to be present in configuration file.": "%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.", "%s a besoin de la section de configuration [%s] dans le fichier de configuration pour fonctionner.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Répondre", "Répondre",
"Anonymous": "Anonymous":
"Anonyme", "Anonyme",
"Anonymous avatar (Vizhash of the IP address)": "Avatar generated from IP address":
"Avatar anonyme (Vizhash de l'adresse IP)", "Avatar anonyme (Vizhash de l'adresse IP)",
"Add comment": "Add comment":
"Ajouter un commentaire", "Ajouter un commentaire",
@ -112,8 +112,8 @@
"Le serveur ne répond pas ou a rencontré une erreur", "Le serveur ne répond pas ou a rencontré une erreur",
"Could not post comment: %s": "Could not post comment: %s":
"Impossible de poster le commentaire : %s", "Impossible de poster le commentaire : %s",
"Sending paste (Please move your mouse for more entropy)…": "Please move your mouse for more entropy…":
"Envoi du paste (Merci de bouger votre souris pour plus d'entropie)…", "Merci de bouger votre souris pour plus d'entropie…",
"Sending paste…": "Sending paste…":
"Envoi du paste…", "Envoi du paste…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -138,7 +138,8 @@
"Source Code": "Code source", "Source Code": "Code source",
"Markdown": "Markdown", "Markdown": "Markdown",
"Download attachment": "Télécharger la pièce jointe", "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 ", "Attach a file": "Attacher un fichier ",
"Remove attachment": "Enlever l'attachement", "Remove attachment": "Enlever l'attachement",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -155,6 +156,9 @@
"Enter password": "Enter password":
"Entrez le mot de passe", "Entrez le mot de passe",
"Loading…": "Chargement…", "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>.":
"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)." "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 +++"
} }

View file

@ -7,8 +7,8 @@
"en": "it", "en": "it",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Questo messaggio non esiste, è scaduto o è stato cancellato.", "Questo messaggio non esiste, è scaduto o è stato cancellato.",
"%s requires php 5.4.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"%s richiede php 5.4.0 o superiore per funzionare. Ci spiace.", "%s richiede php %s o superiore per funzionare. Ci spiace.",
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.":
"%s richiede la presenza della sezione [%s] nei file di configurazione.", "%s richiede la presenza della sezione [%s] nei file di configurazione.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Rispondi", "Rispondi",
"Anonymous": "Anonymous":
"Anonimo", "Anonimo",
"Anonymous avatar (Vizhash of the IP address)": "Avatar generated from IP address":
"Avatar Anonimo (Vizhash dell'indirizzo IP)", "Avatar Anonimo (Vizhash dell'indirizzo IP)",
"Add comment": "Add comment":
"Aggiungi un commento", "Aggiungi un commento",
@ -112,8 +112,8 @@
"errore o mancata risposta dal server", "errore o mancata risposta dal server",
"Could not post comment: %s": "Could not post comment: %s":
"Impossibile inviare il commento: %s", "Impossibile inviare il commento: %s",
"Sending paste (Please move your mouse for more entropy)…": "Please move your mouse for more entropy…":
"Invio messaggio (Muovi il mouse in modo casuale, per generare maggior entropia)…", "Muovi il mouse in modo casuale, per generare maggior entropia…",
"Sending paste…": "Sending paste…":
"Messaggio in fase di invio…", "Messaggio in fase di invio…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -129,7 +129,8 @@
"Source Code": "Codice Sorgente", "Source Code": "Codice Sorgente",
"Markdown": "Markdown", "Markdown": "Markdown",
"Download attachment": "Scarica Allegato", "Download attachment": "Scarica Allegato",
"Cloned file attached.": "Copia del file allegata.", "Cloned: '%s'": "Copia: '%s'",
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
"Attach a file": "Allega un file", "Attach a file": "Allega un file",
"Remove attachment": "Rimuovi allegato", "Remove attachment": "Rimuovi allegato",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password": "Enter password":
"Inserisci la password", "Inserisci la password",
"Loading…": "Loading…", "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>.":
"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)." "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 +++": "+++ no paste text +++"
} }

View file

@ -7,8 +7,8 @@
"en": "no", "en": "no",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Innlegget eksisterer ikke, er utløpt eller har blitt slettet.", "Innlegget eksisterer ikke, er utløpt eller har blitt slettet.",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"Beklager, %s krever php 5.3.0 eller nyere for å kjøre.", "Beklager, %s krever php %s eller nyere for å kjøre.",
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.":
"%s krever konfigurasjonsdel [%s] å være til stede i konfigurasjonsfilen .", "%s krever konfigurasjonsdel [%s] å være til stede i konfigurasjonsfilen .",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Svar", "Svar",
"Anonymous": "Anonymous":
"Anonym", "Anonym",
"Anonymous avatar (Vizhash of the IP address)": "Avatar generated from IP address":
"Anonym avatar (Vizhash av IP adressen)", "Anonym avatar (Vizhash av IP adressen)",
"Add comment": "Add comment":
"Legg til kommentar", "Legg til kommentar",
@ -112,8 +112,8 @@
"server feilet eller svarer ikke", "server feilet eller svarer ikke",
"Could not post comment: %s": "Could not post comment: %s":
"Kunne ikke sende kommentar: %s", "Kunne ikke sende kommentar: %s",
"Sending paste (Please move your mouse for more entropy)…": "Please move your mouse for more entropy…":
"Sender innlegg (Flytt musen for mere entropi)…", "Flytt musen for mere entropi…",
"Sending paste…": "Sending paste…":
"Sender innlegg…", "Sender innlegg…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -129,7 +129,8 @@
"Source Code": "Kildekode", "Source Code": "Kildekode",
"Markdown": "Oppmerket", "Markdown": "Oppmerket",
"Download attachment": "Last ned vedlegg", "Download attachment": "Last ned vedlegg",
"Cloned file attached.": "Kopier vedlegg.", "Cloned: '%s'": "Kopier: '%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", "Attach a file": "Legg til fil",
"Remove attachment": "Slett vedlegg", "Remove attachment": "Slett vedlegg",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password": "Enter password":
"Skriv inn passord", "Skriv inn passord",
"Loading…": "Laster…", "Loading…": "Laster…",
"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>.":
"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 +++": "+++ no paste text +++"
} }

View file

@ -7,8 +7,8 @@
"en": "oc", "en": "oc",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Lo tèxte existís pas, a expirat, o es estat suprimit.", "Lo tèxte existís pas, a expirat, o es estat suprimit.",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"O planhèm, %s necessita php 5.3.0 o superior per foncionar.", "O planhèm, %s necessita php %s o superior per foncionar.",
"%s requires configuration section [%s] to be present in configuration file.": "%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.", "%s fa besonh de la seccion de configuracion [%s] dins lo fichièr de configuracion per foncionar.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Respondre", "Respondre",
"Anonymous": "Anonymous":
"Anonime", "Anonime",
"Anonymous avatar (Vizhash of the IP address)": "Avatar generated from IP address":
"Avatar anonime (Vizhash de l'adreça IP)", "Avatar anonime (Vizhash de l'adreça IP)",
"Add comment": "Add comment":
"Apondre un comentari", "Apondre un comentari",
@ -112,8 +112,8 @@
"Lo servidor respond pas o a rencontrat una error", "Lo servidor respond pas o a rencontrat una error",
"Could not post comment: %s": "Could not post comment: %s":
"Impossible de mandar lo comentari : %s", "Impossible de mandar lo comentari : %s",
"Sending paste (Please move your mouse for more entropy)…": "Please move your mouse for more entropy…":
"Mandadís del tèxte (Mercés de bolegar vòstra mirga per mai entropia)…", "Mercés de bolegar vòstra mirga per mai entropia…",
"Sending paste…": "Sending paste…":
"Mandadís del tèxte…", "Mandadís del tèxte…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -138,7 +138,8 @@
"Source Code": "Còdi font", "Source Code": "Còdi font",
"Markdown": "Markdown", "Markdown": "Markdown",
"Download attachment": "Telecargar la pèça junta", "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 ", "Attach a file": "Juntar un fichièr ",
"Remove attachment": "Levar la pèca junta", "Remove attachment": "Levar la pèca junta",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -155,6 +156,9 @@
"Enter password": "Enter password":
"Picatz lo senhal", "Picatz lo senhal",
"Loading…": "Cargament…", "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>.": "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 +++"
} }

View file

@ -7,8 +7,8 @@
"en": "pl", "en": "pl",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Wklejka nie istnieje, wygasła albo została usunięta.", "Wklejka nie istnieje, wygasła albo została usunięta.",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"%s wymaga PHP w wersji 5.3.0 lub nowszej, sorry.", "%s wymaga PHP w wersji %s lub nowszej, sorry.",
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.":
"%s wymaga obecności sekcji [%s] w pliku konfiguracyjnym.", "%s wymaga obecności sekcji [%s] w pliku konfiguracyjnym.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Odpowiedz", "Odpowiedz",
"Anonymous": "Anonymous":
"Anonim", "Anonim",
"Anonymous avatar (Vizhash of the IP address)": "Avatar generated from IP address":
"Anonimowy avatar (Vizhash z adresu IP)", "Anonimowy avatar (Vizhash z adresu IP)",
"Add comment": "Add comment":
"Dodaj komentarz", "Dodaj komentarz",
@ -112,8 +112,8 @@
"bląd serwera lub brak odpowiedzi", "bląd serwera lub brak odpowiedzi",
"Could not post comment: %s": "Could not post comment: %s":
"Nie udało się wysłać komentarza: %s", "Nie udało się wysłać komentarza: %s",
"Sending paste (Please move your mouse for more entropy)…": "Please move your mouse for more entropy…":
"Wysyłanie wklejki (proszę poruszać myszą aby uzyskać większą entropię)…", "Proszę poruszać myszą aby uzyskać większą entropię…",
"Sending paste…": "Sending paste…":
"Wysyłanie wklejki…", "Wysyłanie wklejki…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -129,7 +129,8 @@
"Source Code": "Kod źródłowy", "Source Code": "Kod źródłowy",
"Markdown": "Markdown", "Markdown": "Markdown",
"Download attachment": "Pobierz załącznik", "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", "Attach a file": "Załącz plik",
"Remove attachment": "Usuń załącznik", "Remove attachment": "Usuń załącznik",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password": "Enter password":
"Wpisz hasło", "Wpisz hasło",
"Loading…": "Loading…", "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 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 +++"
} }

View file

@ -7,8 +7,8 @@
"en": "pt", "en": "pt",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"A cópia não existe, expirou ou já foi excluída.", "A cópia não existe, expirou ou já foi excluída.",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"%s requer php 5.3.0 ou superior para funcionar. Desculpa.", "%s requer php %s ou superior para funcionar. Desculpa.",
"%s requires configuration section [%s] to be present in configuration file.": "%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.", "%s requer que a seção de configuração [% s] esteja no arquivo de configuração.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -93,7 +93,7 @@
"Anonymous": "Anonymous":
"Anônimo", "Anônimo",
"Avatar generated from IP address": "Avatar generated from IP address":
"Avatar (do endereço IP)", "Avatar gerado à partir do endereço IP",
"Add comment": "Add comment":
"Adicionar comentário", "Adicionar comentário",
"Optional nickname…": "Optional nickname…":
@ -130,6 +130,7 @@
"Markdown": "Markdown", "Markdown": "Markdown",
"Download attachment": "Baixar anexo", "Download attachment": "Baixar anexo",
"Cloned: '%s'": "Clonado: '%s'", "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": "Anexar um arquivo", "Attach a file": "Anexar um arquivo",
"Remove attachment": "Remover anexo", "Remove attachment": "Remover anexo",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password": "Enter password":
"Digite a senha", "Digite a senha",
"Loading…": "Carregando…", "Loading…": "Carregando…",
"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>.":
"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>." "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 +++": "+++ no paste text +++"
} }

View file

@ -7,8 +7,8 @@
"en": "ru", "en": "ru",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Запись не существует, просрочена или была удалена.", "Запись не существует, просрочена или была удалена.",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"Для работы %s требуется PHP 5.3.0 или выше. Извините.", "Для работы %s требуется php %s или выше. Извините.",
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.":
"%s необходимо наличие секции [%s] в конфигурационном файле.", "%s необходимо наличие секции [%s] в конфигурационном файле.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -32,7 +32,7 @@
"Paste was properly deleted.": "Paste was properly deleted.":
"Запись была успешно удалена.", "Запись была успешно удалена.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.": "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 requires a modern browser to work.":
"Для работы %s требуется более современный браузер.", "Для работы %s требуется более современный браузер.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:": "Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
@ -92,7 +92,7 @@
"Ответить", "Ответить",
"Anonymous": "Anonymous":
"Аноним", "Аноним",
"Anonymous avatar (Vizhash of the IP address)": "Avatar generated from IP address":
"Анонимный аватар (Vizhash IP адреса)", "Анонимный аватар (Vizhash IP адреса)",
"Add comment": "Add comment":
"Добавить комментарий", "Добавить комментарий",
@ -105,15 +105,15 @@
"Comment posted.": "Comment posted.":
"Комментарий опубликован.", "Комментарий опубликован.",
"Could not refresh display: %s": "Could not refresh display: %s":
"Невозможно обновить данные: %s", "Could not refresh display: %s",
"unknown status": "unknown status":
"неизвестная причина", "неизвестная причина",
"server error or not responding": "server error or not responding":
"ошибка сервера или нет ответа", "ошибка сервера или нет ответа",
"Could not post comment: %s": "Could not post comment: %s":
"Не удалось опубликовать комментарий: %s", "Не удалось опубликовать комментарий: %s",
"Sending paste (Please move your mouse for more entropy)…": "Please move your mouse for more entropy…":
"Отправка записи (Пожалуйста двигайте мышкой для большей энтропии)…", "Пожалуйста двигайте мышкой для большей энтропии…",
"Sending paste…": "Sending paste…":
"Отправка записи…", "Отправка записи…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -138,7 +138,9 @@
"Source Code": "Исходный код", "Source Code": "Исходный код",
"Markdown": "Язык разметки", "Markdown": "Язык разметки",
"Download attachment": "Скачать прикрепленный файл", "Download attachment": "Скачать прикрепленный файл",
"Cloned file attached.": "Дубль файла прикреплен.", "Cloned: '%s'": "Дублировано: '%s'",
"The cloned file '%s' was attached to this paste.":
"Дубликат файла '%s' был прикреплен к этой записи.",
"Attach a file": "Прикрепить файл", "Attach a file": "Прикрепить файл",
"Remove attachment": "Удалить вложение", "Remove attachment": "Удалить вложение",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -154,6 +156,10 @@
"Расшифровать", "Расшифровать",
"Enter password": "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 +++": "+++ в записи нет текста +++"
} }

View file

@ -7,8 +7,8 @@
"en": "sl", "en": "sl",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"Prilepek ne obstaja, mu je potekla življenjska doba, ali pa je izbrisan.", "Prilepek ne obstaja, mu je potekla življenjska doba, ali pa je izbrisan.",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"Oprosti, %s za delovanje potrebuje vsaj php 5.3.0.", "Oprosti, %s za delovanje potrebuje vsaj php %s.",
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.":
"%s potrebuje sekcijo konfiguracij [%s] v konfiguracijski datoteki.", "%s potrebuje sekcijo konfiguracij [%s] v konfiguracijski datoteki.",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Odgovori", "Odgovori",
"Anonymous": "Anonymous":
"Aninomno", "Aninomno",
"Anonymous avatar (Vizhash of the IP address)": "Avatar generated from IP address":
"Anonimen avatar (Vizhash IP naslova)", "Anonimen avatar (Vizhash IP naslova)",
"Add comment": "Add comment":
"Dodaj komentar", "Dodaj komentar",
@ -112,8 +112,8 @@
"napaka na strežniku, ali pa se strežnik ne odziva", "napaka na strežniku, ali pa se strežnik ne odziva",
"Could not post comment: %s": "Could not post comment: %s":
"Komentarja ni bilo mogoče objaviti : %s", "Komentarja ni bilo mogoče objaviti : %s",
"Sending paste (Please move your mouse for more entropy)…": "Please move your mouse for more entropy…":
"Pošiljam prilepek (prosim premakni svojo miško za več entropije) …", "Prosim premakni svojo miško za več entropije…",
"Sending paste…": "Sending paste…":
"Pošiljam prilepek…", "Pošiljam prilepek…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -138,7 +138,8 @@
"Source Code": "Odprta koda", "Source Code": "Odprta koda",
"Markdown": "Markdown", "Markdown": "Markdown",
"Download attachment": "Pretoči priponko", "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", "Attach a file": "Pripni datoteko",
"Remove attachment": "Odstrani priponko", "Remove attachment": "Odstrani priponko",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -155,6 +156,9 @@
"Enter password": "Enter password":
"Prosim vnesi geslo", "Prosim vnesi geslo",
"Loading…": "Loading…", "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 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 +++"
} }

View file

@ -7,8 +7,8 @@
"en": "zh", "en": "zh",
"Paste does not exist, has expired or has been deleted.": "Paste does not exist, has expired or has been deleted.":
"粘贴不存在,已过期或者已被删除。", "粘贴不存在,已过期或者已被删除。",
"%s requires php 5.3.0 or above to work. Sorry.": "%s requires php %s or above to work. Sorry.":
"%s需要工作于PHP 5.3.0及以上版本,抱歉。", "%s需要工作于PHP %s及以上版本,抱歉。",
"%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.":
"%s需要设置配置文件中 [%s] 的部分。", "%s需要设置配置文件中 [%s] 的部分。",
"Please wait %d seconds between each post.": "Please wait %d seconds between each post.":
@ -92,8 +92,8 @@
"回复", "回复",
"Anonymous": "Anonymous":
"匿名", "匿名",
"Anonymous avatar (Vizhash of the IP address)": "Avatar generated from IP address":
"匿名头像 (由IP地址生成Vizhash)", "由IP生成的头像",
"Add comment": "Add comment":
"添加评论", "添加评论",
"Optional nickname…": "Optional nickname…":
@ -112,8 +112,8 @@
"服务器错误或无回应", "服务器错误或无回应",
"Could not post comment: %s": "Could not post comment: %s":
"无法发送评论: %s", "无法发送评论: %s",
"Sending paste (Please move your mouse for more entropy)…": "Please move your mouse for more entropy…":
"粘贴提交中 (请移动鼠标以产生更多熵)…", "请移动鼠标增加随机性…",
"Sending paste…": "Sending paste…":
"粘贴提交中…", "粘贴提交中…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>": "Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -129,7 +129,8 @@
"Source Code": "源代码", "Source Code": "源代码",
"Markdown": "Markdown", "Markdown": "Markdown",
"Download attachment": "下载附件", "Download attachment": "下载附件",
"Cloned file attached.": "已附加克隆的文件", "Cloned: '%s'": "克隆: '%s'",
"The cloned file '%s' was attached to this paste.": "克隆文件 '%s' 已附加到此粘贴。",
"Attach a file": "添加一个附件", "Attach a file": "添加一个附件",
"Remove attachment": "移除附件", "Remove attachment": "移除附件",
"Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password": "Enter password":
"输入密码", "输入密码",
"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>.":
"如果这个消息一直不消失,请参考 <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">这里的 FAQ 进行故障排除</a> (英文版)。" "如果这个消息一直不消失,请参考 <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">这里的 FAQ 进行故障排除</a> (英文版)。",
"+++ no paste text +++": "+++ 没有粘贴内容 +++"
} }

View file

@ -179,20 +179,20 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* *
* @name Helper.urls2links * @name Helper.urls2links
* @function * @function
* @param {Object} element - a jQuery DOM element * @param {Object} $element - a jQuery DOM element
*/ */
me.urls2links = function($element) me.urls2links = function($element)
{ {
var markup = '<a href="$1" rel="nofollow">$1</a>'; var markup = '<a href="$1" rel="nofollow">$1</a>';
$element.html( $element.html(
$element.html().replace( $element.html().replace(
/((http|https|ftp):\/\/[\w?=&.\/-;#@~%+-]+(?![\w\s?&.\/;#~%"=-]*>))/ig, /((http|https|ftp):\/\/[\w?=&.\/-;#@~%+*-]+(?![\w\s?&.\/;#~%"=-]*>))/ig,
markup markup
) )
); );
$element.html( $element.html(
$element.html().replace( $element.html().replace(
/((magnet):[\w?=&.\/-;#@~%+-]+)/ig, /((magnet):[\w?=&.\/-;#@~%+*-]+)/ig,
markup markup
) )
); );
@ -201,6 +201,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
/** /**
* minimal sprintf emulation for %s and %d formats * minimal sprintf emulation for %s and %d formats
* *
* Note that this function needs the parameters in the same order as the
* format strings appear in the string, contrary to the original.
*
* @see {@link https://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format#4795914} * @see {@link https://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format#4795914}
* @name Helper.sprintf * @name Helper.sprintf
* @function * @function
@ -213,27 +216,22 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
var format = args[0], var format = args[0],
i = 1; i = 1;
return format.replace(/%((%)|s|d)/g, function (m) { return format.replace(/%(s|d)/g, function (m) {
// m is the matched format, e.g. %s, %d // m is the matched format, e.g. %s, %d
var val; var val = args[i];
if (m[2]) { // A switch statement so that the formatter can be extended.
val = m[2]; switch (m)
} else { {
val = args[i]; case '%d':
// A switch statement so that the formatter can be extended. val = parseFloat(val);
switch (m) if (isNaN(val)) {
{ val = 0;
case '%d': }
val = parseFloat(val); break;
if (isNaN(val)) { default:
val = 0; // Default is %s
}
break;
default:
// Default is %s
}
++i;
} }
++i;
return val; return val;
}); });
} }
@ -244,7 +242,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @see {@link http://www.w3schools.com/js/js_cookies.asp} * @see {@link http://www.w3schools.com/js/js_cookies.asp}
* @name Helper.getCookie * @name Helper.getCookie
* @function * @function
* @param {string} cname * @param {string} cname - may not be empty
* @return {string} * @return {string}
*/ */
me.getCookie = function(cname) { me.getCookie = function(cname) {
@ -675,7 +673,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @function * @function
* @return {string} func * @return {string} func
*/ */
me.getSymmetricKey = function(func) me.getSymmetricKey = function()
{ {
return sjcl.codec.base64.fromBits(sjcl.random.randomWords(8, 0), 0); return sjcl.codec.base64.fromBits(sjcl.random.randomWords(8, 0), 0);
} }
@ -903,8 +901,6 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
me.isVisible = function($element) me.isVisible = function($element)
{ {
var elementTop = $element.offset().top; var elementTop = $element.offset().top;
var elementBottom = elementTop + $element.outerHeight();
var viewportTop = $(window).scrollTop(); var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height(); var viewportBottom = viewportTop + $(window).height();
@ -985,11 +981,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* Alert/error manager * Alert/error manager
* *
* @name Alert * @name Alert
* @param {object} window
* @param {object} document
* @class * @class
*/ */
var Alert = (function (window, document) { var Alert = (function () {
var me = {}; var me = {};
var $errorMessage, var $errorMessage,
@ -1249,17 +1243,16 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
} }
return me; return me;
})(window, document); })();
/** /**
* handles paste status/result * handles paste status/result
* *
* @name PasteStatus * @name PasteStatus
* @param {object} window * @param {object} window
* @param {object} document
* @class * @class
*/ */
var PasteStatus = (function (window, document) { var PasteStatus = (function (window) {
var me = {}; var me = {};
var $pasteSuccess, var $pasteSuccess,
@ -1402,17 +1395,15 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
} }
return me; return me;
})(window, document); })(window);
/** /**
* password prompt * password prompt
* *
* @name Prompt * @name Prompt
* @param {object} window
* @param {object} document
* @class * @class
*/ */
var Prompt = (function (window, document) { var Prompt = (function () {
var me = {}; var me = {};
var $passwordDecrypt, var $passwordDecrypt,
@ -1512,7 +1503,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
} }
return me; return me;
})(window, document); })();
/** /**
* Manage paste/message input, and preview tab * Manage paste/message input, and preview tab
@ -1520,11 +1511,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* Note that the actual preview is handled by PasteViewer. * Note that the actual preview is handled by PasteViewer.
* *
* @name Editor * @name Editor
* @param {object} window
* @param {object} document
* @class * @class
*/ */
var Editor = (function (window, document) { var Editor = (function () {
var me = {}; var me = {};
var $editorTabs, var $editorTabs,
@ -1728,17 +1717,15 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
} }
return me; return me;
})(window, document); })();
/** /**
* (view) Parse and show paste. * (view) Parse and show paste.
* *
* @name PasteViewer * @name PasteViewer
* @param {object} window
* @param {object} document
* @class * @class
*/ */
var PasteViewer = (function (window, document) { var PasteViewer = (function () {
var me = {}; var me = {};
var $placeholder, var $placeholder,
@ -1904,7 +1891,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @function * @function
* @return {string} * @return {string}
*/ */
me.getText = function(newText) me.getText = function()
{ {
return text; return text;
} }
@ -1981,7 +1968,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
} }
return me; return me;
})(window, document); })();
/** /**
* (view) Show attachment and preview if possible * (view) Show attachment and preview if possible
@ -1998,8 +1985,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
$attachmentPreview, $attachmentPreview,
$attachment; $attachment;
var attachmentChanged = false, var attachmentHasPreview = false;
attachmentHasPreview = false;
/** /**
* sets the attachment but does not yet show it * sets the attachment but does not yet show it
@ -2027,8 +2013,6 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
); );
attachmentHasPreview = true; attachmentHasPreview = true;
} }
attachmentChanged = true;
} }
/** /**
@ -3043,7 +3027,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @private * @private
* @function * @function
* @param {int} status * @param {int} status
* @param {int} data - optional * @param {int} result - optional
*/ */
function success(status, result) function success(status, result)
{ {
@ -3063,7 +3047,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @private * @private
* @function * @function
* @param {int} status - internal code * @param {int} status - internal code
* @param {int} data - original error code * @param {int} result - original error code
*/ */
function fail(status, result) function fail(status, result)
{ {
@ -3107,7 +3091,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* *
* @name Uploader.setUrl * @name Uploader.setUrl
* @function * @function
* @param {function} func * @param {function} newUrl
*/ */
me.setUrl = function(newUrl) me.setUrl = function(newUrl)
{ {
@ -3236,17 +3220,18 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @return {array} * @return {array}
*/ */
me.parseUploadError = function(status, data, doThisThing) { me.parseUploadError = function(status, data, doThisThing) {
var errorArray = ['Error while parsing error message.']; var errorArray;
switch (status) { switch (status) {
case Uploader.error['custom']: case me.error['custom']:
errorArray = ['Could not ' + doThisThing + ': %s', data.message]; errorArray = ['Could not ' + doThisThing + ': %s', data.message];
break; break;
case Uploader.error['unknown']: case me.error['unknown']:
errorArray = ['Could not ' + doThisThing + ': %s', I18n._('unknown status')]; errorArray = ['Could not ' + doThisThing + ': %s', I18n._('unknown status')];
break; break;
case Uploader.error['serverError']: case me.error['serverError']:
errorArray = ['Could not ' + doThisThing + ': %s', I18n._('server error or not responding')]; break; errorArray = ['Could not ' + doThisThing + ': %s', I18n._('server error or not responding')];
break;
default: default:
errorArray = ['Could not ' + doThisThing + ': %s', I18n._('unknown error')]; errorArray = ['Could not ' + doThisThing + ': %s', I18n._('unknown error')];
break; break;
@ -3884,7 +3869,6 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
// show proper elements on screen // show proper elements on screen
PasteDecrypter.run(); PasteDecrypter.run();
return;
} }
/** /**

View file

@ -68,6 +68,225 @@ describe('Helper', 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. &#0 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 () { describe('baseUri', function () {
before(function () { before(function () {
$.PrivateBin.Helper.reset(); $.PrivateBin.Helper.reset();

View file

@ -58,7 +58,7 @@ abstract class AbstractData
* @access public * @access public
* @static * @static
* @param array $options * @param array $options
* @return privatebin_abstract * @return AbstractData
*/ */
public static function getInstance($options) public static function getInstance($options)
{ {
@ -88,7 +88,6 @@ abstract class AbstractData
* *
* @access public * @access public
* @param string $pasteid * @param string $pasteid
* @return void
*/ */
abstract public function delete($pasteid); abstract public function delete($pasteid);
@ -147,7 +146,6 @@ abstract class AbstractData
* *
* @access public * @access public
* @param int $batchsize * @param int $batchsize
* @return void
*/ */
public function purge($batchsize) public function purge($batchsize)
{ {

View file

@ -282,7 +282,6 @@ class Database extends AbstractData
* *
* @access public * @access public
* @param string $pasteid * @param string $pasteid
* @return void
*/ */
public function delete($pasteid) public function delete($pasteid)
{ {
@ -375,11 +374,10 @@ class Database extends AbstractData
$comments[$i]->data = $row['data']; $comments[$i]->data = $row['data'];
$comments[$i]->meta = new stdClass; $comments[$i]->meta = new stdClass;
$comments[$i]->meta->postdate = (int) $row['postdate']; $comments[$i]->meta->postdate = (int) $row['postdate'];
if (array_key_exists('nickname', $row) && !empty($row['nickname'])) { foreach (array('nickname', 'vizhash') as $key) {
$comments[$i]->meta->nickname = $row['nickname']; 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); ksort($comments);
@ -564,7 +562,6 @@ class Database extends AbstractData
* *
* @access private * @access private
* @static * @static
* @return void
*/ */
private static function _createPasteTable() private static function _createPasteTable()
{ {
@ -589,7 +586,6 @@ class Database extends AbstractData
* *
* @access private * @access private
* @static * @static
* @return void
*/ */
private static function _createCommentTable() private static function _createCommentTable()
{ {
@ -616,7 +612,6 @@ class Database extends AbstractData
* *
* @access private * @access private
* @static * @static
* @return void
*/ */
private static function _createConfigTable() private static function _createConfigTable()
{ {
@ -651,7 +646,6 @@ class Database extends AbstractData
* @access private * @access private
* @static * @static
* @param string $oldversion * @param string $oldversion
* @return void
*/ */
private static function _upgradeDatabase($oldversion) private static function _upgradeDatabase($oldversion)
{ {

View file

@ -12,8 +12,8 @@
namespace PrivateBin\Data; namespace PrivateBin\Data;
use PrivateBin\Json;
use PrivateBin\Model\Paste; use PrivateBin\Model\Paste;
use PrivateBin\Persistence\DataStore;
/** /**
* Filesystem * Filesystem
@ -22,15 +22,6 @@ use PrivateBin\Model\Paste;
*/ */
class Filesystem extends AbstractData class Filesystem extends AbstractData
{ {
/**
* directory where data is stored
*
* @access private
* @static
* @var string
*/
private static $_dir = 'data/';
/** /**
* get instance of singleton * get instance of singleton
* *
@ -41,17 +32,16 @@ class Filesystem extends AbstractData
*/ */
public static function getInstance($options = null) 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 given update the data directory
if ( if (
is_array($options) && is_array($options) &&
array_key_exists('dir', $options) array_key_exists('dir', $options)
) { ) {
self::$_dir = $options['dir'] . DIRECTORY_SEPARATOR; DataStore::setPath($options['dir']);
}
// if needed initialize the singleton
if (!(self::$_instance instanceof self)) {
self::$_instance = new self;
self::_init();
} }
return self::$_instance; return self::$_instance;
} }
@ -62,19 +52,19 @@ class Filesystem extends AbstractData
* @access public * @access public
* @param string $pasteid * @param string $pasteid
* @param array $paste * @param array $paste
* @throws Exception
* @return bool * @return bool
*/ */
public function create($pasteid, $paste) public function create($pasteid, $paste)
{ {
$storagedir = self::_dataid2path($pasteid); $storagedir = self::_dataid2path($pasteid);
if (is_file($storagedir . $pasteid)) { $file = $storagedir . $pasteid;
if (is_file($file)) {
return false; return false;
} }
if (!is_dir($storagedir)) { if (!is_dir($storagedir)) {
mkdir($storagedir, 0700, true); 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 * @access public
* @param string $pasteid * @param string $pasteid
* @return void
*/ */
public function delete($pasteid) public function delete($pasteid)
{ {
@ -155,20 +144,19 @@ class Filesystem extends AbstractData
* @param string $parentid * @param string $parentid
* @param string $commentid * @param string $commentid
* @param array $comment * @param array $comment
* @throws Exception
* @return bool * @return bool
*/ */
public function createComment($pasteid, $parentid, $commentid, $comment) public function createComment($pasteid, $parentid, $commentid, $comment)
{ {
$storagedir = self::_dataid2discussionpath($pasteid); $storagedir = self::_dataid2discussionpath($pasteid);
$filename = $pasteid . '.' . $commentid . '.' . $parentid; $file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid;
if (is_file($storagedir . $filename)) { if (is_file($file)) {
return false; return false;
} }
if (!is_dir($storagedir)) { if (!is_dir($storagedir)) {
mkdir($storagedir, 0700, true); 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) protected function _getExpiredPastes($batchsize)
{ {
$pastes = array(); $pastes = array();
$mainpath = DataStore::getPath();
$firstLevel = array_filter( $firstLevel = array_filter(
scandir(self::$_dir), scandir($mainpath),
'self::_isFirstLevelDir' 'self::_isFirstLevelDir'
); );
if (count($firstLevel) > 0) { if (count($firstLevel) > 0) {
@ -246,7 +235,7 @@ class Filesystem extends AbstractData
for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) { for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) {
$firstKey = array_rand($firstLevel); $firstKey = array_rand($firstLevel);
$secondLevel = array_filter( $secondLevel = array_filter(
scandir(self::$_dir . $firstLevel[$firstKey]), scandir($mainpath . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]),
'self::_isSecondLevelDir' 'self::_isSecondLevelDir'
); );
@ -257,8 +246,9 @@ class Filesystem extends AbstractData
} }
$secondKey = array_rand($secondLevel); $secondKey = array_rand($secondLevel);
$path = self::$_dir . $firstLevel[$firstKey] . $path = $mainpath . DIRECTORY_SEPARATOR .
DIRECTORY_SEPARATOR . $secondLevel[$secondKey]; $firstLevel[$firstKey] . DIRECTORY_SEPARATOR .
$secondLevel[$secondKey];
if (!is_dir($path)) { if (!is_dir($path)) {
continue; continue;
} }
@ -292,29 +282,6 @@ class Filesystem extends AbstractData
return $pastes; 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. * Convert paste id to storage path.
* *
@ -332,8 +299,10 @@ class Filesystem extends AbstractData
*/ */
private static function _dataid2path($dataid) private static function _dataid2path($dataid)
{ {
return self::$_dir . substr($dataid, 0, 2) . DIRECTORY_SEPARATOR . return DataStore::getPath(
substr($dataid, 2, 2) . DIRECTORY_SEPARATOR; 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) private static function _isFirstLevelDir($element)
{ {
return self::_isSecondLevelDir($element) && return self::_isSecondLevelDir($element) &&
is_dir(self::$_dir . DIRECTORY_SEPARATOR . $element); is_dir(DataStore::getPath($element));
} }
/** /**

View file

@ -135,15 +135,17 @@ class I18n
* *
* @access public * @access public
* @static * @static
* @return void
*/ */
public static function loadTranslations() public static function loadTranslations()
{ {
$availableLanguages = self::getAvailableLanguages(); $availableLanguages = self::getAvailableLanguages();
// check if the lang cookie was set and that language exists // check if the lang cookie was set and that language exists
if (array_key_exists('lang', $_COOKIE) && in_array($_COOKIE['lang'], $availableLanguages)) { if (
$match = $_COOKIE['lang']; array_key_exists('lang', $_COOKIE) &&
($key = array_search($_COOKIE['lang'], $availableLanguages)) !== false
) {
$match = $availableLanguages[$key];
} }
// find a translation file matching the browsers language preferences // find a translation file matching the browsers language preferences
else { else {
@ -256,7 +258,6 @@ class I18n
* @access public * @access public
* @static * @static
* @param string $lang * @param string $lang
* @return void
*/ */
public static function setLanguageFallback($lang) public static function setLanguageFallback($lang)
{ {

View file

@ -40,7 +40,6 @@ class Model
* Factory constructor. * Factory constructor.
* *
* @param configuration $conf * @param configuration $conf
* @return void
*/ */
public function __construct(Configuration $conf) public function __construct(Configuration $conf)
{ {
@ -64,8 +63,6 @@ class Model
/** /**
* Checks if a purge is necessary and triggers it if yes. * Checks if a purge is necessary and triggers it if yes.
*
* @return void
*/ */
public function purge() public function purge()
{ {

View file

@ -63,7 +63,6 @@ abstract class AbstractModel
* @access public * @access public
* @param Configuration $configuration * @param Configuration $configuration
* @param AbstractData $storage * @param AbstractData $storage
* @return void
*/ */
public function __construct(Configuration $configuration, AbstractData $storage) public function __construct(Configuration $configuration, AbstractData $storage)
{ {
@ -90,7 +89,6 @@ abstract class AbstractModel
* @access public * @access public
* @param string $id * @param string $id
* @throws Exception * @throws Exception
* @return void
*/ */
public function setId($id) public function setId($id)
{ {
@ -106,7 +104,6 @@ abstract class AbstractModel
* @access public * @access public
* @param string $data * @param string $data
* @throws Exception * @throws Exception
* @return void
*/ */
public function setData($data) public function setData($data)
{ {
@ -133,7 +130,6 @@ abstract class AbstractModel
* *
* @access public * @access public
* @throws Exception * @throws Exception
* @return void
*/ */
abstract public function store(); abstract public function store();
@ -142,7 +138,6 @@ abstract class AbstractModel
* *
* @access public * @access public
* @throws Exception * @throws Exception
* @return void
*/ */
abstract public function delete(); abstract public function delete();

View file

@ -61,7 +61,6 @@ class Comment extends AbstractModel
* *
* @access public * @access public
* @throws Exception * @throws Exception
* @return void
*/ */
public function store() public function store()
{ {
@ -101,7 +100,6 @@ class Comment extends AbstractModel
* *
* @access public * @access public
* @throws Exception * @throws Exception
* @return void
*/ */
public function delete() public function delete()
{ {
@ -129,7 +127,6 @@ class Comment extends AbstractModel
* @access public * @access public
* @param Paste $paste * @param Paste $paste
* @throws Exception * @throws Exception
* @return void
*/ */
public function setPaste(Paste $paste) public function setPaste(Paste $paste)
{ {
@ -154,7 +151,6 @@ class Comment extends AbstractModel
* @access public * @access public
* @param string $id * @param string $id
* @throws Exception * @throws Exception
* @return void
*/ */
public function setParentId($id) public function setParentId($id)
{ {
@ -184,7 +180,6 @@ class Comment extends AbstractModel
* @access public * @access public
* @param string $nickname * @param string $nickname
* @throws Exception * @throws Exception
* @return void
*/ */
public function setNickname($nickname) public function setNickname($nickname)
{ {

View file

@ -75,7 +75,6 @@ class Paste extends AbstractModel
* *
* @access public * @access public
* @throws Exception * @throws Exception
* @return void
*/ */
public function store() public function store()
{ {
@ -103,7 +102,6 @@ class Paste extends AbstractModel
* *
* @access public * @access public
* @throws Exception * @throws Exception
* @return void
*/ */
public function delete() public function delete()
{ {
@ -183,7 +181,6 @@ class Paste extends AbstractModel
* @access public * @access public
* @param string $attachment * @param string $attachment
* @throws Exception * @throws Exception
* @return void
*/ */
public function setAttachment($attachment) public function setAttachment($attachment)
{ {
@ -199,7 +196,6 @@ class Paste extends AbstractModel
* @access public * @access public
* @param string $attachmentname * @param string $attachmentname
* @throws Exception * @throws Exception
* @return void
*/ */
public function setAttachmentName($attachmentname) public function setAttachmentName($attachmentname)
{ {
@ -214,7 +210,6 @@ class Paste extends AbstractModel
* *
* @access public * @access public
* @param string $expiration * @param string $expiration
* @return void
*/ */
public function setExpiration($expiration) public function setExpiration($expiration)
{ {
@ -236,7 +231,6 @@ class Paste extends AbstractModel
* @access public * @access public
* @param string $burnafterreading * @param string $burnafterreading
* @throws Exception * @throws Exception
* @return void
*/ */
public function setBurnafterreading($burnafterreading = '1') public function setBurnafterreading($burnafterreading = '1')
{ {
@ -257,7 +251,6 @@ class Paste extends AbstractModel
* @access public * @access public
* @param string $opendiscussion * @param string $opendiscussion
* @throws Exception * @throws Exception
* @return void
*/ */
public function setOpendiscussion($opendiscussion = '1') public function setOpendiscussion($opendiscussion = '1')
{ {
@ -281,7 +274,6 @@ class Paste extends AbstractModel
* @access public * @access public
* @param string $format * @param string $format
* @throws Exception * @throws Exception
* @return void
*/ */
public function setFormatter($format) public function setFormatter($format)
{ {

View file

@ -36,7 +36,6 @@ abstract class AbstractPersistence
* @access public * @access public
* @static * @static
* @param string $path * @param string $path
* @return void
*/ */
public static function setPath($path) public static function setPath($path)
{ {
@ -80,27 +79,23 @@ abstract class AbstractPersistence
* @access protected * @access protected
* @static * @static
* @throws Exception * @throws Exception
* @return void
*/ */
protected static function _initialize() protected static function _initialize()
{ {
// Create storage directory if it does not exist. // Create storage directory if it does not exist.
if (!is_dir(self::$_path)) { if (!is_dir(self::$_path)) {
if (!@mkdir(self::$_path)) { if (!@mkdir(self::$_path, 0700)) {
throw new Exception('unable to create directory ' . self::$_path, 10); throw new Exception('unable to create directory ' . self::$_path, 10);
} }
} }
// Create .htaccess file if it does not exist.
$file = self::$_path . DIRECTORY_SEPARATOR . '.htaccess'; $file = self::$_path . DIRECTORY_SEPARATOR . '.htaccess';
if (!is_file($file)) { if (!is_file($file)) {
$writtenBytes = @file_put_contents( $writtenBytes = @file_put_contents(
$file, $file,
'Allow from none' . PHP_EOL . 'Require all denied' . PHP_EOL,
'Deny from all' . PHP_EOL,
LOCK_EX LOCK_EX
); );
if ($writtenBytes === false || $writtenBytes < 30) { if ($writtenBytes === false || $writtenBytes < 19) {
throw new Exception('unable to write to file ' . $file, 11); throw new Exception('unable to write to file ' . $file, 11);
} }
} }

View file

@ -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;
}
}
}

View file

@ -36,7 +36,6 @@ class PurgeLimiter extends AbstractPersistence
* @access public * @access public
* @static * @static
* @param int $limit * @param int $limit
* @return void
*/ */
public static function setLimit($limit) public static function setLimit($limit)
{ {
@ -49,7 +48,6 @@ class PurgeLimiter extends AbstractPersistence
* @access public * @access public
* @static * @static
* @param Configuration $conf * @param Configuration $conf
* @return void
*/ */
public static function setConfiguration(Configuration $conf) public static function setConfiguration(Configuration $conf)
{ {

View file

@ -95,7 +95,6 @@ class ServerSalt extends AbstractPersistence
* @access public * @access public
* @static * @static
* @param string $path * @param string $path
* @return void
*/ */
public static function setPath($path) public static function setPath($path)
{ {

View file

@ -45,7 +45,6 @@ class TrafficLimiter extends AbstractPersistence
* @access public * @access public
* @static * @static
* @param int $limit * @param int $limit
* @return void
*/ */
public static function setLimit($limit) public static function setLimit($limit)
{ {
@ -58,7 +57,6 @@ class TrafficLimiter extends AbstractPersistence
* @access public * @access public
* @static * @static
* @param Configuration $conf * @param Configuration $conf
* @return void
*/ */
public static function setConfiguration(Configuration $conf) public static function setConfiguration(Configuration $conf)
{ {

View file

@ -30,6 +30,13 @@ class PrivateBin
*/ */
const VERSION = '1.1'; 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 * show the same error message if the paste expired or does not exist
* *
@ -116,12 +123,11 @@ class PrivateBin
* *
* @access public * @access public
* @throws Exception * @throws Exception
* @return void
*/ */
public function __construct() public function __construct()
{ {
if (version_compare(PHP_VERSION, '5.4.0') < 0) { if (version_compare(PHP_VERSION, self::MIN_PHP_VERSION) < 0) {
throw new Exception(I18n::_('%s requires php 5.4.0 or above to work. Sorry.', I18n::_('PrivateBin')), 1); 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) { 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); 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 * initialize privatebin
* *
* @access private * @access private
* @return void
*/ */
private function _init() 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->_conf = new Configuration;
$this->_model = new Model($this->_conf); $this->_model = new Model($this->_conf);
$this->_request = new Request; $this->_request = new Request;
@ -324,7 +318,6 @@ class PrivateBin
* @access private * @access private
* @param string $dataid * @param string $dataid
* @param string $deletetoken * @param string $deletetoken
* @return void
*/ */
private function _delete($dataid, $deletetoken) private function _delete($dataid, $deletetoken)
{ {
@ -368,7 +361,6 @@ class PrivateBin
* *
* @access private * @access private
* @param string $dataid * @param string $dataid
* @return void
*/ */
private function _read($dataid) private function _read($dataid)
{ {
@ -401,7 +393,6 @@ class PrivateBin
* Display PrivateBin frontend. * Display PrivateBin frontend.
* *
* @access private * @access private
* @return void
*/ */
private function _view() private function _view()
{ {
@ -465,7 +456,6 @@ class PrivateBin
* *
* @access private * @access private
* @param string $type * @param string $type
* @return void
*/ */
private function _jsonld($type) private function _jsonld($type)
{ {
@ -498,7 +488,6 @@ class PrivateBin
* @param int $status * @param int $status
* @param string $message * @param string $message
* @param array $other * @param array $other
* @return void
*/ */
private function _return_message($status, $message, $other = array()) private function _return_message($status, $message, $other = array())
{ {

View file

@ -41,7 +41,7 @@ class Request
const MIME_XHTML = 'application/xhtml+xml'; const MIME_XHTML = 'application/xhtml+xml';
/** /**
* Input stream to use for PUT parameter parsing. * Input stream to use for PUT parameter parsing
* *
* @access private * @access private
* @var string * @var string
@ -49,7 +49,7 @@ class Request
private static $_inputStream = 'php://input'; private static $_inputStream = 'php://input';
/** /**
* Operation to perform. * Operation to perform
* *
* @access private * @access private
* @var string * @var string
@ -57,7 +57,7 @@ class Request
private $_operation = 'view'; private $_operation = 'view';
/** /**
* Request parameters. * Request parameters
* *
* @access private * @access private
* @var array * @var array
@ -65,7 +65,7 @@ class Request
private $_params = array(); private $_params = array();
/** /**
* If we are in a JSON API context. * If we are in a JSON API context
* *
* @access private * @access private
* @var bool * @var bool
@ -73,10 +73,9 @@ class Request
private $_isJsonApi = false; private $_isJsonApi = false;
/** /**
* Constructor. * Constructor
* *
* @access public * @access public
* @return void
*/ */
public function __construct() public function __construct()
{ {
@ -122,7 +121,7 @@ class Request
} }
/** /**
* Get current operation. * Get current operation
* *
* @access public * @access public
* @return string * @return string
@ -133,7 +132,7 @@ class Request
} }
/** /**
* Get a request parameter. * Get a request parameter
* *
* @access public * @access public
* @param string $param * @param string $param
@ -146,7 +145,7 @@ class Request
} }
/** /**
* If we are in a JSON API context. * If we are in a JSON API context
* *
* @access public * @access public
* @return bool * @return bool
@ -157,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 * @param string $input
*/ */
@ -167,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 * Adapted from: https://stackoverflow.com/questions/3770513/detect-browser-language-in-php#3771447
* *

View file

@ -35,7 +35,6 @@ class View
* @access public * @access public
* @param string $name * @param string $name
* @param mixed $value * @param mixed $value
* @return void
*/ */
public function assign($name, $value) public function assign($name, $value)
{ {
@ -48,7 +47,6 @@ class View
* @access public * @access public
* @param string $template * @param string $template
* @throws Exception * @throws Exception
* @return void
*/ */
public function draw($template) public function draw($template)
{ {

View file

@ -61,7 +61,6 @@ class Vizhash16x16
* constructor * constructor
* *
* @access public * @access public
* @return void
*/ */
public function __construct() public function __construct()
{ {
@ -210,7 +209,6 @@ class Vizhash16x16
* @param resource $image * @param resource $image
* @param int $action * @param int $action
* @param int $color * @param int $color
* @return void
*/ */
private function drawshape($image, $action, $color) private function drawshape($image, $action, $color)
{ {

View file

@ -69,7 +69,7 @@ if ($MARKDOWN):
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-7/bLmiTErcH3lMJi1JxXk/lb20NUO7TCqasWeFybnNhnfOUnJ9GQGqPVJxPf+7fnw9dgLa1s18FXQuRanLD8Hw==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-xfoNRo43UxDcd7m1P2IsvSPcOeGJo1oUjbA+CNCBoBilKRU3Iuqbf7awv3knP50bX7PVGEjtS6yJ2KtOtqnhTA==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->

View file

@ -47,7 +47,7 @@ if ($MARKDOWN):
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-7/bLmiTErcH3lMJi1JxXk/lb20NUO7TCqasWeFybnNhnfOUnJ9GQGqPVJxPf+7fnw9dgLa1s18FXQuRanLD8Hw==" crossorigin="anonymous"></script> <script type="text/javascript" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-xfoNRo43UxDcd7m1P2IsvSPcOeGJo1oUjbA+CNCBoBilKRU3Iuqbf7awv3knP50bX7PVGEjtS6yJ2KtOtqnhTA==" crossorigin="anonymous"></script>
<!--[if lt IE 10]> <!--[if lt IE 10]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style> <style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]--> <![endif]-->

1
tst/.gitignore vendored
View file

@ -1 +0,0 @@
/ConfigurationCombinationsTest.php

View file

@ -1,2 +0,0 @@
Allow from none
Deny from all

View file

@ -172,22 +172,24 @@ class Helper
*/ */
public static function rmDir($path) public static function rmDir($path)
{ {
$path .= DIRECTORY_SEPARATOR; if (is_dir($path)) {
$dir = dir($path); $path .= DIRECTORY_SEPARATOR;
while (false !== ($file = $dir->read())) { $dir = dir($path);
if ($file != '.' && $file != '..') { while (false !== ($file = $dir->read())) {
if (is_dir($path . $file)) { if ($file != '.' && $file != '..') {
self::rmDir($path . $file); if (is_dir($path . $file)) {
} elseif (is_file($path . $file)) { self::rmDir($path . $file);
if (!unlink($path . $file)) { } elseif (is_file($path . $file)) {
throw new Exception('Error deleting file "' . $path . $file . '".'); if (!unlink($path . $file)) {
throw new Exception('Error deleting file "' . $path . $file . '".');
}
} }
} }
} }
} $dir->close();
$dir->close(); if (!rmdir($path)) {
if (!rmdir($path)) { throw new Exception('Error deleting directory "' . $path . '".');
throw new Exception('Error deleting directory "' . $path . '".'); }
} }
} }

View file

@ -311,7 +311,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
'vizhash BLOB, ' . 'vizhash BLOB, ' .
'postdate INT );' '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 // check if version number was upgraded in created configuration table
$statement = $db->prepare('SELECT value FROM foo_config WHERE id LIKE ?'); $statement = $db->prepare('SELECT value FROM foo_config WHERE id LIKE ?');

View file

@ -8,16 +8,26 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
private $_path; private $_path;
private $_invalidPath;
public function setUp() public function setUp()
{ {
/* Setup Routine */ /* Setup Routine */
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data'; $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
$this->_model = Filesystem::getInstance(array('dir' => $this->_path)); $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() public function tearDown()
{ {
/* Tear Down Routine */ /* Tear Down Routine */
chmod($this->_invalidPath, 0700);
Helper::rmDir($this->_path); 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->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->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->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 = json_decode(json_encode(Helper::getComment()));
$comment->id = Helper::getCommentId(); $comment->id = Helper::getCommentId();
$comment->parentid = Helper::getPasteId(); $comment->parentid = Helper::getPasteId();
@ -99,10 +110,6 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
} }
} }
/**
* @expectedException Exception
* @expectedExceptionCode 90
*/
public function testErrorDetection() public function testErrorDetection()
{ {
$this->_model->delete(Helper::getPasteId()); $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'); $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does still not exist');
} }
/**
* @expectedException Exception
* @expectedExceptionCode 90
*/
public function testCommentErrorDetection() public function testCommentErrorDetection()
{ {
$this->_model->delete(Helper::getPasteId()); $this->_model->delete(Helper::getPasteId());

View file

@ -142,4 +142,36 @@ class I18nTest extends PHPUnit_Framework_TestCase
I18n::loadTranslations(); I18n::loadTranslations();
$this->assertEquals('some string + 1', I18n::_('some %s + %d', 'string', 1), 'browser language en'); $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"
);
}
}
}
}
} }

View file

@ -98,6 +98,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
new PrivateBin; new PrivateBin;
$content = ob_get_contents(); $content = ob_get_contents();
ob_end_clean(); ob_end_clean();
unlink($file);
$response = json_decode($content, true); $response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs status'); $this->assertEquals(0, $response['status'], 'outputs status');
$this->assertEquals(Helper::getPasteId(), $response['id'], 'outputted paste ID matches input'); $this->assertEquals(Helper::getPasteId(), $response['id'], 'outputted paste ID matches input');
@ -132,6 +133,7 @@ class JsonApiTest extends PHPUnit_Framework_TestCase
new PrivateBin; new PrivateBin;
$content = ob_get_contents(); $content = ob_get_contents();
ob_end_clean(); ob_end_clean();
unlink($file);
$response = json_decode($content, true); $response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs status'); $this->assertEquals(0, $response['status'], 'outputs status');
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted'); $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');

View file

@ -82,6 +82,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
$comment = $paste->getComment(Helper::getPasteId()); $comment = $paste->getComment(Helper::getPasteId());
$comment->setData($commentData['data']); $comment->setData($commentData['data']);
$comment->setNickname($commentData['meta']['nickname']); $comment->setNickname($commentData['meta']['nickname']);
$comment->getParentId();
$comment->store(); $comment->store();
$comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId()); $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'); $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 * @expectedException Exception
* @expectedExceptionCode 62 * @expectedExceptionCode 62
@ -199,6 +221,37 @@ class ModelTest extends PHPUnit_Framework_TestCase
$paste->getComment(Helper::getPasteId()); $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() public function testExpiration()
{ {
$pasteData = Helper::getPaste(); $pasteData = Helper::getPaste();

View file

@ -140,21 +140,18 @@ class PrivateBinTest extends PHPUnit_Framework_TestCase
public function testHtaccess() public function testHtaccess()
{ {
$this->reset(); $this->reset();
$dirs = array('cfg', 'lib'); $file = $this->_path . DIRECTORY_SEPARATOR . '.htaccess';
foreach ($dirs as $dir) { @unlink($file);
$file = PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess';
@unlink($file); $_POST = Helper::getPaste();
} $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST';
$_SERVER['REMOTE_ADDR'] = '::1';
ob_start(); ob_start();
new PrivateBin; new PrivateBin;
ob_end_clean(); ob_end_clean();
foreach ($dirs as $dir) {
$file = PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess'; $this->assertFileExists($file, 'htaccess recreated');
$this->assertFileExists(
$file,
"$dir htaccess recreated"
);
}
} }
/** /**

View file

@ -63,6 +63,7 @@ class RequestTest extends PHPUnit_Framework_TestCase
file_put_contents($file, 'data=foo'); file_put_contents($file, 'data=foo');
Request::setInputStream($file); Request::setInputStream($file);
$request = new Request; $request = new Request;
unlink($file);
$this->assertTrue($request->isJsonApiCall(), 'is JSON Api call'); $this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
$this->assertEquals('create', $request->getOperation()); $this->assertEquals('create', $request->getOperation());
$this->assertEquals('foo', $request->getParam('data')); $this->assertEquals('foo', $request->getParam('data'));

View file

@ -1,11 +1,13 @@
<?php <?php
use PrivateBin\Persistence\ServerSalt;
use PrivateBin\Sjcl; use PrivateBin\Sjcl;
class SjclTest extends PHPUnit_Framework_TestCase class SjclTest extends PHPUnit_Framework_TestCase
{ {
public function testSjclValidatorValidatesCorrectly() public function testSjclValidatorValidatesCorrectly()
{ {
ServerSalt::setPath(sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data');
$paste = Helper::getPasteWithAttachment(); $paste = Helper::getPasteWithAttachment();
$this->assertTrue(Sjcl::isValid($paste['data']), 'valid sjcl'); $this->assertTrue(Sjcl::isValid($paste['data']), 'valid sjcl');
$this->assertTrue(Sjcl::isValid($paste['attachment']), 'valid sjcl'); $this->assertTrue(Sjcl::isValid($paste['attachment']), 'valid sjcl');