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
js/node_modules/
tst/log/
tst/ConfigurationCombinationsTest.php
.settings
.buildpath
.project

View file

@ -1,15 +1,26 @@
language: php
sudo: false
php:
- 5.5
- 5.6
- 7.0
- '5.4'
- '5.5'
- '5.6'
- '7.0'
- '7.1'
# as this is a php project, node.js v4 (for JS unit testing) isn't installed
install:
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install 4
before_script:
- composer install -n
- npm install -g mocha
- cd js
- npm install jsverify jsdom jsdom-global
- cd ..
script:
- cd tst && ../vendor/bin/phpunit
- cd ../js && mocha
after_script:
- cd ..

View file

@ -10,7 +10,7 @@ check the options and adjust them as you see fit.
### Requirements
- PHP version 5.3 or above
- PHP version 5.4 or above
- _one_ of the following sources of cryptographically safe randomness is required:
- PHP 7 or higher
- [Libsodium](https://download.libsodium.org/libsodium/content/installation/) and it's [PHP extension](https://paragonie.com/book/pecl-libsodium/read/00-intro.md#installing-libsodium)

View file

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

View file

@ -7,8 +7,8 @@
"en": "de",
"Paste does not exist, has expired or has been deleted.":
"Diesen Text gibt es nicht, er ist abgelaufen oder wurde gelöscht.",
"%s requires php 5.3.0 or above to work. Sorry.":
"%s benötigt PHP 5.3.0 oder höher, um zu funktionieren. Sorry.",
"%s requires php %s or above to work. Sorry.":
"%s benötigt PHP %s oder höher, um zu funktionieren. Sorry.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s benötigt den Konfigurationsabschnitt [%s] in der Konfigurationsdatei um zu funktionieren.",
"Please wait %d seconds between each post.":
@ -151,6 +151,5 @@
"Preparing new paste…": "Bereite neues Paste vor…",
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
"Wenn diese Nachricht nicht mehr verschwindet, schau bitte in <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">die FAQ</a> (englisch), um zu sehen, wie der Fehler behoben werden kann.",
"+++ no paste text +++":
"+++ kein Paste-Text +++"
"+++ no paste text +++": "+++ kein Paste-Text +++"
}

View file

@ -7,8 +7,8 @@
"en": "es",
"Paste does not exist, has expired or has been deleted.":
"El texto no existe, ha caducado o ha sido eliminado.",
"%s requires php 5.3.0 or above to work. Sorry.":
"%s requiere php 5.3.0 o superior para funcionar. Lo siento.",
"%s requires php %s or above to work. Sorry.":
"%s requiere php %s o superior para funcionar. Lo siento.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s requiere que la sección de configuración [%s] esté presente en el archivo de configuración.",
"Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Responder",
"Anonymous":
"Anónimo",
"Anonymous avatar (Vizhash of the IP address)":
"Avatar generated from IP address":
"Avatar anónimo (Vizhash de la dirección IP)",
"Add comment":
"Añadir comentario",
@ -112,8 +112,8 @@
"Error del servidor o el servidor no responde",
"Could not post comment: %s":
"No fue posible publicar comentario: %s",
"Sending paste (Please move your mouse for more entropy)…":
"Enviando texto (Por favor, mueva el ratón para mayor entropía)…",
"Please move your mouse for more entropy…":
"Por favor, mueva el ratón para mayor entropía…",
"Sending paste…":
"Enviando texto…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -129,7 +129,8 @@
"Source Code": "Código fuente",
"Markdown": "Markdown",
"Download attachment": "Descargar adjunto",
"Cloned file attached.": "Archivo clonado adjunto.",
"Cloned: '%s'": "Clonado: '%s'.",
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
"Attach a file": "Adjuntar archivo",
"Remove attachment": "Remover adjunto",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password":
"Ingrese contraseña",
"Loading…": "Cargando…",
"Decrypting paste…": "Decrypting paste…",
"Preparing new paste…": "Preparing new paste…",
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
"En caso de que este mensaje nunca desaparezca por favor revise <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">este FAQ para obtener información para solucionar problemas</a>."
"En caso de que este mensaje nunca desaparezca por favor revise <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">este FAQ para obtener información para solucionar problemas</a>.",
"+++ no paste text +++": "+++ no paste text +++"
}

View file

@ -7,8 +7,8 @@
"en": "fr",
"Paste does not exist, has expired or has been deleted.":
"Le paste n'existe pas, a expiré, ou a été supprimé.",
"%s requires php 5.3.0 or above to work. Sorry.":
"Désolé, %s nécessite php 5.3.0 ou supérieur pour fonctionner.",
"%s requires php %s or above to work. Sorry.":
"Désolé, %s nécessite php %s ou supérieur pour fonctionner.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s a besoin de la section de configuration [%s] dans le fichier de configuration pour fonctionner.",
"Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Répondre",
"Anonymous":
"Anonyme",
"Anonymous avatar (Vizhash of the IP address)":
"Avatar generated from IP address":
"Avatar anonyme (Vizhash de l'adresse IP)",
"Add comment":
"Ajouter un commentaire",
@ -112,8 +112,8 @@
"Le serveur ne répond pas ou a rencontré une erreur",
"Could not post comment: %s":
"Impossible de poster le commentaire : %s",
"Sending paste (Please move your mouse for more entropy)…":
"Envoi du paste (Merci de bouger votre souris pour plus d'entropie)…",
"Please move your mouse for more entropy…":
"Merci de bouger votre souris pour plus d'entropie…",
"Sending paste…":
"Envoi du paste…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -138,7 +138,8 @@
"Source Code": "Code source",
"Markdown": "Markdown",
"Download attachment": "Télécharger la pièce jointe",
"Cloned file attached.": "Cloner le fichier attaché.",
"Cloned: '%s'": "Cloner '%s'",
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
"Attach a file": "Attacher un fichier ",
"Remove attachment": "Enlever l'attachement",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -155,6 +156,9 @@
"Enter password":
"Entrez le mot de passe",
"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>.":
"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",
"Paste does not exist, has expired or has been deleted.":
"Questo messaggio non esiste, è scaduto o è stato cancellato.",
"%s requires php 5.4.0 or above to work. Sorry.":
"%s richiede php 5.4.0 o superiore per funzionare. Ci spiace.",
"%s requires php %s or above to work. Sorry.":
"%s richiede php %s o superiore per funzionare. Ci spiace.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s richiede la presenza della sezione [%s] nei file di configurazione.",
"Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Rispondi",
"Anonymous":
"Anonimo",
"Anonymous avatar (Vizhash of the IP address)":
"Avatar generated from IP address":
"Avatar Anonimo (Vizhash dell'indirizzo IP)",
"Add comment":
"Aggiungi un commento",
@ -112,8 +112,8 @@
"errore o mancata risposta dal server",
"Could not post comment: %s":
"Impossibile inviare il commento: %s",
"Sending paste (Please move your mouse for more entropy)…":
"Invio messaggio (Muovi il mouse in modo casuale, per generare maggior entropia)…",
"Please move your mouse for more entropy…":
"Muovi il mouse in modo casuale, per generare maggior entropia…",
"Sending paste…":
"Messaggio in fase di invio…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -129,7 +129,8 @@
"Source Code": "Codice Sorgente",
"Markdown": "Markdown",
"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",
"Remove attachment": "Rimuovi allegato",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password":
"Inserisci la password",
"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>.":
"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",
"Paste does not exist, has expired or has been deleted.":
"Innlegget eksisterer ikke, er utløpt eller har blitt slettet.",
"%s requires php 5.3.0 or above to work. Sorry.":
"Beklager, %s krever php 5.3.0 eller nyere for å kjøre.",
"%s requires php %s or above to work. Sorry.":
"Beklager, %s krever php %s eller nyere for å kjøre.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s krever konfigurasjonsdel [%s] å være til stede i konfigurasjonsfilen .",
"Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Svar",
"Anonymous":
"Anonym",
"Anonymous avatar (Vizhash of the IP address)":
"Avatar generated from IP address":
"Anonym avatar (Vizhash av IP adressen)",
"Add comment":
"Legg til kommentar",
@ -112,8 +112,8 @@
"server feilet eller svarer ikke",
"Could not post comment: %s":
"Kunne ikke sende kommentar: %s",
"Sending paste (Please move your mouse for more entropy)…":
"Sender innlegg (Flytt musen for mere entropi)…",
"Please move your mouse for more entropy…":
"Flytt musen for mere entropi…",
"Sending paste…":
"Sender innlegg…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -129,7 +129,8 @@
"Source Code": "Kildekode",
"Markdown": "Oppmerket",
"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",
"Remove attachment": "Slett vedlegg",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password":
"Skriv inn passord",
"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>.":
"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",
"Paste does not exist, has expired or has been deleted.":
"Lo tèxte existís pas, a expirat, o es estat suprimit.",
"%s requires php 5.3.0 or above to work. Sorry.":
"O planhèm, %s necessita php 5.3.0 o superior per foncionar.",
"%s requires php %s or above to work. Sorry.":
"O planhèm, %s necessita php %s o superior per foncionar.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s fa besonh de la seccion de configuracion [%s] dins lo fichièr de configuracion per foncionar.",
"Please wait %d seconds between each post.":
@ -92,7 +92,7 @@
"Respondre",
"Anonymous":
"Anonime",
"Anonymous avatar (Vizhash of the IP address)":
"Avatar generated from IP address":
"Avatar anonime (Vizhash de l'adreça IP)",
"Add comment":
"Apondre un comentari",
@ -112,8 +112,8 @@
"Lo servidor respond pas o a rencontrat una error",
"Could not post comment: %s":
"Impossible de mandar lo comentari : %s",
"Sending paste (Please move your mouse for more entropy)…":
"Mandadís del tèxte (Mercés de bolegar vòstra mirga per mai entropia)…",
"Please move your mouse for more entropy…":
"Mercés de bolegar vòstra mirga per mai entropia…",
"Sending paste…":
"Mandadís del tèxte…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -138,7 +138,8 @@
"Source Code": "Còdi font",
"Markdown": "Markdown",
"Download attachment": "Telecargar la pèça junta",
"Cloned file attached.": "Clonar lo fichièr junt.",
"Cloned: '%s'": "Clonar: '%s'",
"The cloned file '%s' was attached to this paste.": "The cloned file '%s' was attached to this paste.",
"Attach a file": "Juntar un fichièr ",
"Remove attachment": "Levar la pèca junta",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -155,6 +156,9 @@
"Enter password":
"Picatz lo senhal",
"Loading…": "Cargament…",
"Decrypting paste…": "Decrypting paste…",
"Preparing new paste…": "Preparing new paste…",
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
"Se per cas aqueste messatge quita pas de s'afichar mercés de gaitar <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">aquesta FAQ per las solucions</a> (en Anglés)."
"Se per cas aqueste messatge quita pas de s'afichar mercés de gaitar <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">aquesta FAQ per las solucions</a> (en Anglés).",
"+++ no paste text +++": "+++ no paste text +++"
}

View file

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

View file

@ -7,8 +7,8 @@
"en": "pt",
"Paste does not exist, has expired or has been deleted.":
"A cópia não existe, expirou ou já foi excluída.",
"%s requires php 5.3.0 or above to work. Sorry.":
"%s requer php 5.3.0 ou superior para funcionar. Desculpa.",
"%s requires php %s or above to work. Sorry.":
"%s requer php %s ou superior para funcionar. Desculpa.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s requer que a seção de configuração [% s] esteja no arquivo de configuração.",
"Please wait %d seconds between each post.":
@ -93,7 +93,7 @@
"Anonymous":
"Anônimo",
"Avatar generated from IP address":
"Avatar (do endereço IP)",
"Avatar gerado à partir do endereço IP",
"Add comment":
"Adicionar comentário",
"Optional nickname…":
@ -130,6 +130,7 @@
"Markdown": "Markdown",
"Download attachment": "Baixar anexo",
"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",
"Remove attachment": "Remover anexo",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password":
"Digite a senha",
"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>.":
"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",
"Paste does not exist, has expired or has been deleted.":
"Запись не существует, просрочена или была удалена.",
"%s requires php 5.3.0 or above to work. Sorry.":
"Для работы %s требуется PHP 5.3.0 или выше. Извините.",
"%s requires php %s or above to work. Sorry.":
"Для работы %s требуется php %s или выше. Извините.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s необходимо наличие секции [%s] в конфигурационном файле.",
"Please wait %d seconds between each post.":
@ -32,7 +32,7 @@
"Paste was properly deleted.":
"Запись была успешно удалена.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"Для работы %s требуется включенный JavaScript.<br />Приносим извинения за неудобства..",
"Для работы %s требуется включенный JavaScript.<br />Приносим извинения за неудобства.",
"%s requires a modern browser to work.":
"Для работы %s требуется более современный браузер.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
@ -92,7 +92,7 @@
"Ответить",
"Anonymous":
"Аноним",
"Anonymous avatar (Vizhash of the IP address)":
"Avatar generated from IP address":
"Анонимный аватар (Vizhash IP адреса)",
"Add comment":
"Добавить комментарий",
@ -105,15 +105,15 @@
"Comment posted.":
"Комментарий опубликован.",
"Could not refresh display: %s":
"Невозможно обновить данные: %s",
"Could not refresh display: %s",
"unknown status":
"неизвестная причина",
"server error or not responding":
"ошибка сервера или нет ответа",
"Could not post comment: %s":
"Не удалось опубликовать комментарий: %s",
"Sending paste (Please move your mouse for more entropy)…":
"Отправка записи (Пожалуйста двигайте мышкой для большей энтропии)…",
"Please move your mouse for more entropy…":
"Пожалуйста двигайте мышкой для большей энтропии…",
"Sending paste…":
"Отправка записи…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -138,7 +138,9 @@
"Source Code": "Исходный код",
"Markdown": "Язык разметки",
"Download attachment": "Скачать прикрепленный файл",
"Cloned file attached.": "Дубль файла прикреплен.",
"Cloned: '%s'": "Дублировано: '%s'",
"The cloned file '%s' was attached to this paste.":
"Дубликат файла '%s' был прикреплен к этой записи.",
"Attach a file": "Прикрепить файл",
"Remove attachment": "Удалить вложение",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -154,6 +156,10 @@
"Расшифровать",
"Enter password":
"Введите пароль",
"Uploading paste… Please wait.":
"Отправка записи… Пожалуйста подождите."
"Loading…": "Загрузка…",
"Decrypting paste…": "Расшифровка записи…",
"Preparing new paste…": "Подготовка новой записи…",
"In case this message never disappears please have a look at <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">this FAQ for information to troubleshoot</a>.":
"Если данное сообщение не исчезает длительное время, посмотрите <a href=\"https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away\">этот FAQ с информацией о возможном решении проблемы (на английском)</a>.",
"+++ no paste text +++": "+++ в записи нет текста +++"
}

View file

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

View file

@ -7,8 +7,8 @@
"en": "zh",
"Paste does not exist, has expired or has been deleted.":
"粘贴不存在,已过期或者已被删除。",
"%s requires php 5.3.0 or above to work. Sorry.":
"%s需要工作于PHP 5.3.0及以上版本,抱歉。",
"%s requires php %s or above to work. Sorry.":
"%s需要工作于PHP %s及以上版本,抱歉。",
"%s requires configuration section [%s] to be present in configuration file.":
"%s需要设置配置文件中 [%s] 的部分。",
"Please wait %d seconds between each post.":
@ -92,8 +92,8 @@
"回复",
"Anonymous":
"匿名",
"Anonymous avatar (Vizhash of the IP address)":
"匿名头像 (由IP地址生成Vizhash)",
"Avatar generated from IP address":
"由IP生成的头像",
"Add comment":
"添加评论",
"Optional nickname…":
@ -112,8 +112,8 @@
"服务器错误或无回应",
"Could not post comment: %s":
"无法发送评论: %s",
"Sending paste (Please move your mouse for more entropy)…":
"粘贴提交中 (请移动鼠标以产生更多熵)…",
"Please move your mouse for more entropy…":
"请移动鼠标增加随机性…",
"Sending paste…":
"粘贴提交中…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
@ -129,7 +129,8 @@
"Source Code": "源代码",
"Markdown": "Markdown",
"Download attachment": "下载附件",
"Cloned file attached.": "已附加克隆的文件",
"Cloned: '%s'": "克隆: '%s'",
"The cloned file '%s' was attached to this paste.": "克隆文件 '%s' 已附加到此粘贴。",
"Attach a file": "添加一个附件",
"Remove attachment": "移除附件",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
@ -146,6 +147,9 @@
"Enter password":
"输入密码",
"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> (英文版)。"
"如果这个消息一直不消失,请参考 <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
* @function
* @param {Object} element - a jQuery DOM element
* @param {Object} $element - a jQuery DOM element
*/
me.urls2links = function($element)
{
var markup = '<a href="$1" rel="nofollow">$1</a>';
$element.html(
$element.html().replace(
/((http|https|ftp):\/\/[\w?=&.\/-;#@~%+-]+(?![\w\s?&.\/;#~%"=-]*>))/ig,
/((http|https|ftp):\/\/[\w?=&.\/-;#@~%+*-]+(?![\w\s?&.\/;#~%"=-]*>))/ig,
markup
)
);
$element.html(
$element.html().replace(
/((magnet):[\w?=&.\/-;#@~%+-]+)/ig,
/((magnet):[\w?=&.\/-;#@~%+*-]+)/ig,
markup
)
);
@ -201,6 +201,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
/**
* 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}
* @name Helper.sprintf
* @function
@ -213,27 +216,22 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
var args = Array.prototype.slice.call(arguments);
var format = args[0],
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
var val;
if (m[2]) {
val = m[2];
} else {
val = args[i];
// A switch statement so that the formatter can be extended.
switch (m)
{
case '%d':
val = parseFloat(val);
if (isNaN(val)) {
val = 0;
}
break;
default:
// Default is %s
}
++i;
var val = args[i];
// A switch statement so that the formatter can be extended.
switch (m)
{
case '%d':
val = parseFloat(val);
if (isNaN(val)) {
val = 0;
}
break;
default:
// Default is %s
}
++i;
return val;
});
}
@ -244,7 +242,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @see {@link http://www.w3schools.com/js/js_cookies.asp}
* @name Helper.getCookie
* @function
* @param {string} cname
* @param {string} cname - may not be empty
* @return {string}
*/
me.getCookie = function(cname) {
@ -675,7 +673,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @function
* @return {string} func
*/
me.getSymmetricKey = function(func)
me.getSymmetricKey = function()
{
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)
{
var elementTop = $element.offset().top;
var elementBottom = elementTop + $element.outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
@ -985,11 +981,9 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* Alert/error manager
*
* @name Alert
* @param {object} window
* @param {object} document
* @class
*/
var Alert = (function (window, document) {
var Alert = (function () {
var me = {};
var $errorMessage,
@ -1249,17 +1243,16 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
}
return me;
})(window, document);
})();
/**
* handles paste status/result
*
* @name PasteStatus
* @param {object} window
* @param {object} document
* @class
*/
var PasteStatus = (function (window, document) {
var PasteStatus = (function (window) {
var me = {};
var $pasteSuccess,
@ -1402,17 +1395,15 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
}
return me;
})(window, document);
})(window);
/**
* password prompt
*
* @name Prompt
* @param {object} window
* @param {object} document
* @class
*/
var Prompt = (function (window, document) {
var Prompt = (function () {
var me = {};
var $passwordDecrypt,
@ -1512,7 +1503,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
}
return me;
})(window, document);
})();
/**
* 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.
*
* @name Editor
* @param {object} window
* @param {object} document
* @class
*/
var Editor = (function (window, document) {
var Editor = (function () {
var me = {};
var $editorTabs,
@ -1728,17 +1717,15 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
}
return me;
})(window, document);
})();
/**
* (view) Parse and show paste.
*
* @name PasteViewer
* @param {object} window
* @param {object} document
* @class
*/
var PasteViewer = (function (window, document) {
var PasteViewer = (function () {
var me = {};
var $placeholder,
@ -1904,7 +1891,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @function
* @return {string}
*/
me.getText = function(newText)
me.getText = function()
{
return text;
}
@ -1981,7 +1968,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
}
return me;
})(window, document);
})();
/**
* (view) Show attachment and preview if possible
@ -1998,8 +1985,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
$attachmentPreview,
$attachment;
var attachmentChanged = false,
attachmentHasPreview = false;
var attachmentHasPreview = false;
/**
* sets the attachment but does not yet show it
@ -2027,8 +2013,6 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
);
attachmentHasPreview = true;
}
attachmentChanged = true;
}
/**
@ -3043,7 +3027,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @private
* @function
* @param {int} status
* @param {int} data - optional
* @param {int} result - optional
*/
function success(status, result)
{
@ -3063,7 +3047,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @private
* @function
* @param {int} status - internal code
* @param {int} data - original error code
* @param {int} result - original error code
*/
function fail(status, result)
{
@ -3107,7 +3091,7 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
*
* @name Uploader.setUrl
* @function
* @param {function} func
* @param {function} newUrl
*/
me.setUrl = function(newUrl)
{
@ -3236,17 +3220,18 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
* @return {array}
*/
me.parseUploadError = function(status, data, doThisThing) {
var errorArray = ['Error while parsing error message.'];
var errorArray;
switch (status) {
case Uploader.error['custom']:
case me.error['custom']:
errorArray = ['Could not ' + doThisThing + ': %s', data.message];
break;
case Uploader.error['unknown']:
case me.error['unknown']:
errorArray = ['Could not ' + doThisThing + ': %s', I18n._('unknown status')];
break;
case Uploader.error['serverError']:
errorArray = ['Could not ' + doThisThing + ': %s', I18n._('server error or not responding')]; break;
case me.error['serverError']:
errorArray = ['Could not ' + doThisThing + ': %s', I18n._('server error or not responding')];
break;
default:
errorArray = ['Could not ' + doThisThing + ': %s', I18n._('unknown error')];
break;
@ -3884,7 +3869,6 @@ jQuery.PrivateBin = function($, sjcl, Base64, RawDeflate) {
// show proper elements on screen
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 () {
before(function () {
$.PrivateBin.Helper.reset();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

@ -30,6 +30,13 @@ class PrivateBin
*/
const VERSION = '1.1';
/**
* minimal required PHP version
*
* @const string
*/
const MIN_PHP_VERSION = '5.4.0';
/**
* show the same error message if the paste expired or does not exist
*
@ -116,12 +123,11 @@ class PrivateBin
*
* @access public
* @throws Exception
* @return void
*/
public function __construct()
{
if (version_compare(PHP_VERSION, '5.4.0') < 0) {
throw new Exception(I18n::_('%s requires php 5.4.0 or above to work. Sorry.', I18n::_('PrivateBin')), 1);
if (version_compare(PHP_VERSION, self::MIN_PHP_VERSION) < 0) {
throw new Exception(I18n::_('%s requires php %s or above to work. Sorry.', I18n::_('PrivateBin'), self::MIN_PHP_VERSION), 1);
}
if (strlen(PATH) < 0 && substr(PATH, -1) !== DIRECTORY_SEPARATOR) {
throw new Exception(I18n::_('%s requires the PATH to end in a "%s". Please update the PATH in your index.php.', I18n::_('PrivateBin'), DIRECTORY_SEPARATOR), 5);
@ -164,21 +170,9 @@ class PrivateBin
* initialize privatebin
*
* @access private
* @return void
*/
private function _init()
{
foreach (array('cfg', 'lib') as $dir) {
if (!is_file(PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess')) {
file_put_contents(
PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess',
'Allow from none' . PHP_EOL .
'Deny from all' . PHP_EOL,
LOCK_EX
);
}
}
$this->_conf = new Configuration;
$this->_model = new Model($this->_conf);
$this->_request = new Request;
@ -324,7 +318,6 @@ class PrivateBin
* @access private
* @param string $dataid
* @param string $deletetoken
* @return void
*/
private function _delete($dataid, $deletetoken)
{
@ -368,7 +361,6 @@ class PrivateBin
*
* @access private
* @param string $dataid
* @return void
*/
private function _read($dataid)
{
@ -401,7 +393,6 @@ class PrivateBin
* Display PrivateBin frontend.
*
* @access private
* @return void
*/
private function _view()
{
@ -465,7 +456,6 @@ class PrivateBin
*
* @access private
* @param string $type
* @return void
*/
private function _jsonld($type)
{
@ -498,7 +488,6 @@ class PrivateBin
* @param int $status
* @param string $message
* @param array $other
* @return void
*/
private function _return_message($status, $message, $other = array())
{

View file

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

View file

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

View file

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

View file

@ -69,7 +69,7 @@ if ($MARKDOWN):
<?php
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]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![endif]-->

View file

@ -47,7 +47,7 @@ if ($MARKDOWN):
<?php
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]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
<![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)
{
$path .= DIRECTORY_SEPARATOR;
$dir = dir($path);
while (false !== ($file = $dir->read())) {
if ($file != '.' && $file != '..') {
if (is_dir($path . $file)) {
self::rmDir($path . $file);
} elseif (is_file($path . $file)) {
if (!unlink($path . $file)) {
throw new Exception('Error deleting file "' . $path . $file . '".');
if (is_dir($path)) {
$path .= DIRECTORY_SEPARATOR;
$dir = dir($path);
while (false !== ($file = $dir->read())) {
if ($file != '.' && $file != '..') {
if (is_dir($path . $file)) {
self::rmDir($path . $file);
} elseif (is_file($path . $file)) {
if (!unlink($path . $file)) {
throw new Exception('Error deleting file "' . $path . $file . '".');
}
}
}
}
}
$dir->close();
if (!rmdir($path)) {
throw new Exception('Error deleting directory "' . $path . '".');
$dir->close();
if (!rmdir($path)) {
throw new Exception('Error deleting directory "' . $path . '".');
}
}
}

View file

@ -311,7 +311,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
'vizhash BLOB, ' .
'postdate INT );'
);
$this->assertInstanceOf(Database::class, Database::getInstance($this->_options));
$this->assertInstanceOf('PrivateBin\\Data\\Database', Database::getInstance($this->_options));
// check if version number was upgraded in created configuration table
$statement = $db->prepare('SELECT value FROM foo_config WHERE id LIKE ?');

View file

@ -8,16 +8,26 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
private $_path;
private $_invalidPath;
public function setUp()
{
/* Setup Routine */
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
$this->_model = Filesystem::getInstance(array('dir' => $this->_path));
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
$this->_invalidPath = $this->_path . DIRECTORY_SEPARATOR . 'bar';
$this->_model = Filesystem::getInstance(array('dir' => $this->_path));
if (!is_dir($this->_path)) {
mkdir($this->_path);
}
if (!is_dir($this->_invalidPath)) {
mkdir($this->_invalidPath);
}
}
public function tearDown()
{
/* Tear Down Routine */
chmod($this->_invalidPath, 0700);
Helper::rmDir($this->_path);
}
@ -37,6 +47,7 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
$this->assertFalse($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment does not yet exist');
$this->assertTrue($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()), 'store comment');
$this->assertTrue($this->_model->existsComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId()), 'comment exists after storing it');
$this->assertFalse($this->_model->createComment(Helper::getPasteId(), Helper::getPasteId(), Helper::getCommentId(), Helper::getComment()), 'unable to store the same comment twice');
$comment = json_decode(json_encode(Helper::getComment()));
$comment->id = Helper::getCommentId();
$comment->parentid = Helper::getPasteId();
@ -99,10 +110,6 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
}
}
/**
* @expectedException Exception
* @expectedExceptionCode 90
*/
public function testErrorDetection()
{
$this->_model->delete(Helper::getPasteId());
@ -112,10 +119,6 @@ class FilesystemTest extends PHPUnit_Framework_TestCase
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does still not exist');
}
/**
* @expectedException Exception
* @expectedExceptionCode 90
*/
public function testCommentErrorDetection()
{
$this->_model->delete(Helper::getPasteId());

View file

@ -142,4 +142,36 @@ class I18nTest extends PHPUnit_Framework_TestCase
I18n::loadTranslations();
$this->assertEquals('some string + 1', I18n::_('some %s + %d', 'string', 1), 'browser language en');
}
public function testMessageIdsExistInAllLanguages()
{
$messageIds = array();
$languages = array();
$dir = dir(PATH . 'i18n');
while (false !== ($file = $dir->read())) {
if (strlen($file) === 7) {
$language = substr($file, 0, 2);
$languageMessageIds = array_keys(
json_decode(
file_get_contents(PATH . 'i18n' . DIRECTORY_SEPARATOR . $file),
true
)
);
$messageIds = array_unique(array_merge($messageIds, $languageMessageIds));
$languages[$language] = $languageMessageIds;
}
}
foreach ($messageIds as $messageId) {
foreach (array_keys($languages) as $language) {
// most languages don't translate the data size units, ignore those
if ($messageId !== 'B' && strlen($messageId) !== 3 && strpos($messageId, 'B', 2) !== 2) {
$this->assertContains(
$messageId,
$languages[$language],
"message ID '$messageId' exists in translation file $language.json"
);
}
}
}
}
}

View file

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

View file

@ -82,6 +82,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
$comment = $paste->getComment(Helper::getPasteId());
$comment->setData($commentData['data']);
$comment->setNickname($commentData['meta']['nickname']);
$comment->getParentId();
$comment->store();
$comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
@ -189,6 +190,27 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->assertFalse(Paste::isValidId('../bar/baz'), 'path attack');
}
/**
* @expectedException Exception
* @expectedExceptionCode 64
*/
public function testInvalidPaste()
{
$this->_model->getPaste(Helper::getPasteId())->delete();
$paste = $this->_model->getPaste(Helper::getPasteId());
$paste->get();
}
/**
* @expectedException Exception
* @expectedExceptionCode 61
*/
public function testInvalidData()
{
$paste = $this->_model->getPaste();
$paste->setData('');
}
/**
* @expectedException Exception
* @expectedExceptionCode 62
@ -199,6 +221,37 @@ class ModelTest extends PHPUnit_Framework_TestCase
$paste->getComment(Helper::getPasteId());
}
/**
* @expectedException Exception
* @expectedExceptionCode 67
*/
public function testInvalidCommentDeletedPaste()
{
$pasteData = Helper::getPaste();
$paste = $this->_model->getPaste(Helper::getPasteId());
$paste->setData($pasteData['data']);
$paste->store();
$comment = $paste->getComment(Helper::getPasteId());
$paste->delete();
$comment->store();
}
/**
* @expectedException Exception
* @expectedExceptionCode 68
*/
public function testInvalidCommentData()
{
$pasteData = Helper::getPaste();
$paste = $this->_model->getPaste(Helper::getPasteId());
$paste->setData($pasteData['data']);
$paste->store();
$comment = $paste->getComment(Helper::getPasteId());
$comment->store();
}
public function testExpiration()
{
$pasteData = Helper::getPaste();

View file

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

View file

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

View file

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