Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2dd8b94b05 | ||
|
|
608605cd54 | ||
|
|
a41d0ca4dd | ||
|
|
844c4d15e9 | ||
|
|
a111357fae | ||
|
|
47efedf23c | ||
|
|
801cdc627e | ||
|
|
39e865ca64 | ||
|
|
50075ea948 | ||
|
|
ed9c4f45f4 | ||
|
|
e144739dec | ||
|
|
8de24fae67 | ||
|
|
9274564162 | ||
|
|
e04e75adf3 | ||
|
|
c72932d653 | ||
|
|
895df63206 | ||
|
|
f25661beda | ||
|
|
ec8851e46c | ||
|
|
106141efa4 | ||
|
|
61903665df | ||
|
|
0e53d1ee86 | ||
|
|
9dde7f034a | ||
|
|
428a9d9c41 | ||
|
|
da42968d7c | ||
|
|
be8883d10e | ||
|
|
b26fb08732 | ||
|
|
588e01fbec | ||
|
|
b060d57524 | ||
|
|
2f15d4c70a | ||
|
|
108cf69f8b | ||
|
|
c83ba8256f | ||
|
|
eee7b0144a | ||
|
|
5e47feb7e1 | ||
|
|
9a370d33ea | ||
|
|
9ac9f9e1a7 | ||
|
|
952f8b7b9a | ||
|
|
18f32f3625 | ||
|
|
72ace70b04 | ||
|
|
ce331e8271 | ||
|
|
b883d5eb4c | ||
|
|
3099e10dfa | ||
|
|
d74172064b | ||
|
|
9687144c92 | ||
|
|
a2af88a36e | ||
|
|
28776ac178 | ||
|
|
3edeefd799 |
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -1,4 +1,4 @@
|
||||
doc/* export-ignore
|
||||
tst/* export-ignore
|
||||
doc/ export-ignore
|
||||
tst/ export-ignore
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.gitignore export-ignore
|
||||
|
||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,12 +1,29 @@
|
||||
# ZeroBin version history #
|
||||
|
||||
* **0.21 (2015-09-19)**:
|
||||
* ADDED: Translations for German, French and Polish, language selection menu (optional)
|
||||
* ADDED: File upload and image display support (optional)
|
||||
* ADDED: Markdown format support
|
||||
* ADDED: "bootstrap-compact" template that hides some of the options in a drop down menu to ensure the nav bar fitting on one line on smaller screen sizes
|
||||
* FIXING: Various usability issues with different screen sizes / device types in the "bootstrap" template
|
||||
* CHANGED: Instead of having different options to enable and preselect certain formats there is now a generic `[formatter_options]` section where formats can be added to the displayed format drop down menu. A `defaultformatter` can be set, it defaults to "plaintext". The `syntaxhighlighting` configuration got deprecated.
|
||||
* `zerobin.js` got a major refactoring:
|
||||
* moved from global namespace into anonymous function
|
||||
* events are no longer set via "onclick" attributes in the templates, but bound by from JS side
|
||||
* for simpler maintenance the functions were grouped into objects: zerobin (display logic, event handling), filter (compression,
|
||||
encryption), i18n (translation, counterpart of i18n.php) and helper (stateless utilities)
|
||||
* Wiki pages were added to address common topics:
|
||||
* [Upgrading from ZeroBin 0.19 Alpha](https://github.com/elrido/ZeroBin/wiki/Upgrading-from-ZeroBin-0.19-Alpha)
|
||||
* [ZeroBin Directory of public servers](https://github.com/elrido/ZeroBin/wiki/ZeroBin-Directory)
|
||||
* [Translation](https://github.com/elrido/ZeroBin/wiki/Translation)
|
||||
* [Templates](https://github.com/elrido/ZeroBin/wiki/Templates)
|
||||
* **0.20 (2015-09-03)**:
|
||||
* ADDED: Password protected pastes (optional)
|
||||
* ADDED: configuration options for highlighting, password, discussions, expiration times, rate limiting
|
||||
* ADDED: JSON-only retrieval of paste incl. discussion, used to be able to refresh paste when posting a comment
|
||||
* ADDED: bootstrap CSS based template
|
||||
* CHANGE: "Burn after reading" pastes are now deleted only after the paste was successfully decrypted via callback. This prevents accidental deletion by chatbots following URLs and the like. Usage of a password is suggested to ensure only the desired recipient is able to encrypt it.
|
||||
* CHANGE: the "opendiscussion" option now only controls if the discussion checkbox is preselected. Use "discussion = false" to disable the discussion feature completely (which also removes the checkbox from the template).
|
||||
* CHANGED: "Burn after reading" pastes are now deleted only after the paste was successfully decrypted via callback. This prevents accidental deletion by chatbots following URLs and the like. Usage of a password is suggested to ensure only the desired recipient is able to encrypt it.
|
||||
* CHANGED: the "opendiscussion" option now only controls if the discussion checkbox is preselected. Use "discussion = false" to disable the discussion feature completely (which also removes the checkbox from the template).
|
||||
* FIXING: Behaviour of several conflicting configuration options. As a general measure unit tests for 9 of the options and all their possible configurations were added via a unit test generator.
|
||||
* updated JS libraries: jquery to 1.11.3, sjcl to 1.0.2, base64.js to 2.1.9, deflate to 0.5, inflate to 0.3 and prettify to latest
|
||||
* generally improved documentation, both inline phpdoc / JSdoc source code documentation, as well as Wiki pages on installation, configuration, development and JSON-API
|
||||
|
||||
@@ -5,5 +5,12 @@ Sébastien Sauvage - original idea and main developer
|
||||
Alexey Gladkov - syntax highlighting
|
||||
Greg Knaddison - robots.txt
|
||||
MrKooky - HTML5 markup, CSS cleanup
|
||||
Simon Rupf - MVC refactoring, configuration support and unit tests
|
||||
Simon Rupf - MVC refactoring, configuration, i18n and unit tests
|
||||
Hexalyse - Password protection
|
||||
Viktor Stanchev - File upload support
|
||||
|
||||
Translations:
|
||||
Hexalyse - French
|
||||
Kuba Niewiarowski - Polish
|
||||
Gabbalo - German
|
||||
Draky50110 - French
|
||||
|
||||
116
INSTALL.md
116
INSTALL.md
@@ -1,20 +1,47 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
For Administrators
|
||||
------------------
|
||||
## Basic installation
|
||||
|
||||
In the index.php in the main folder you can define a different PATH. This is
|
||||
useful if you want to secure your installation and want to move the
|
||||
configuration, data files, templates and PHP libraries (directories cfg, data,
|
||||
lib, tpl and tst) outside of your document root. This new location must still
|
||||
be accessible to your webserver / PHP process.
|
||||
**TL;DR:** Download the [latest release archive](https://github.com/elrido/ZeroBin/releases/latest)
|
||||
and extract it in your web hosts folder were you want to install your ZeroBin instance.
|
||||
|
||||
> ### PATH Example ###
|
||||
> Your zerobin installation lives in a subfolder called "paste" inside of your
|
||||
### Requirements
|
||||
|
||||
- PHP version 5.2.6 or above
|
||||
- GD extension
|
||||
- mcrypt extension (recommended)
|
||||
- some disk space or (optional) a database supported by PDO
|
||||
- A web browser with javascript support
|
||||
|
||||
### Configuration
|
||||
|
||||
In the file `cfg/conf.ini` you can configure ZeroBin. The config file is divided
|
||||
into multiple sections, which are enclosed in square brackets.
|
||||
|
||||
In the `[main]` section you can enable or disable the discussion feature, set the
|
||||
limit of stored pastes and comments in bytes. The `[traffic]` section lets you
|
||||
set a time limit in seconds. Users may not post more often then this limit to
|
||||
your ZeroBin installation.
|
||||
|
||||
More details can be found in the
|
||||
[configuration documentation](https://github.com/elrido/ZeroBin/wiki/Configuration).
|
||||
|
||||
## Advanced installation
|
||||
|
||||
### Changing the path
|
||||
|
||||
In the index.php you can define a different `PATH`. This is useful to secure your
|
||||
installation. You can move the configuration, data files, templates and PHP
|
||||
libraries (directories cfg, data, lib, tpl, tmp and tst) outside of your document
|
||||
root. This new location must still be accessible to your webserver / PHP process
|
||||
([open_basedir setting](http://php.net/manual/en/ini.core.php#ini.open-basedir)).
|
||||
|
||||
> #### PATH Example
|
||||
> Your zerobin installation lives in a subfolder called "paste" inside of your
|
||||
> document root. The URL looks like this:
|
||||
> http://example.com/paste/
|
||||
> The ZeroBin folder on your webserver is really:
|
||||
> The full path of ZeroBin on your webserver is:
|
||||
> /home/example.com/htdocs/paste
|
||||
>
|
||||
> When setting the path like this:
|
||||
@@ -22,29 +49,27 @@ be accessible to your webserver / PHP process.
|
||||
> ZeroBin will look for your includes here:
|
||||
> /home/example.com/secret/zerobin
|
||||
|
||||
In the file "cfg/conf.ini" you can configure ZeroBin. The config file is
|
||||
divided into multiple sections, which are enclosed in square brackets. In the
|
||||
"[main]" section you can enable or disable the discussion feature, set the
|
||||
limit of stored pastes and comments in bytes. The "[traffic]" section lets you
|
||||
set a time limit in seconds. Users may not post more often then this limit to
|
||||
your ZeroBin.
|
||||
### Using a database instead of flat files
|
||||
|
||||
Finally the "[model]" and "[model_options]" sections let you configure your
|
||||
favourite way of storing the pastes and discussions on your server.
|
||||
"zerobin_data" is the default model, which stores everything in files in the
|
||||
data folder. This is the recommended setup for low traffic sites. Under high
|
||||
load, in distributed setups or if you are not allowed to store files locally,
|
||||
you might want to switch to the "zerobin_db" model. This lets you store your
|
||||
data in a database. Basically all databases that are supported by PDO (PHP
|
||||
data objects) may be used. Automatic table creation is provided for pdo_ibm,
|
||||
pdo_informix, pdo_mssql, pdo_mysql, pdo_oci, pdo_pgsql and pdo_sqlite. You may
|
||||
want to provide a table prefix, if you have to share the zerobin database with
|
||||
another application. The table prefix option is called "tbl".
|
||||
In the configuration file the `[model]` and `[model_options]` sections let you
|
||||
configure your favourite way of storing the pastes and discussions on your server.
|
||||
|
||||
> ### Note ###
|
||||
> The "zerobin_db" model has only been tested with SQLite and MySQL, although
|
||||
> it would not be recommended to use SQLite in a production environment. If you
|
||||
> gain any experience running ZeroBin on other RDBMS, please let us know.
|
||||
`zerobin_data` is the default model, which stores everything in files in the data
|
||||
folder. This is the recommended setup for most sites.
|
||||
|
||||
Under high load, in distributed setups or if you are not allowed to store files
|
||||
locally, you might want to switch to the `zerobin_db` model. This lets you store
|
||||
your data in a database. Basically all databases that are supported by
|
||||
[PDO](http://php.net/manual/en/book.pdo.php) may be used. Automatic table
|
||||
creation is provided for `pdo_ibm`, `pdo_informix`, `pdo_mssql`, `pdo_mysql`,
|
||||
`pdo_oci`, `pdo_pgsql` and `pdo_sqlite`. You may want to provide a table prefix,
|
||||
if you have to share the zerobin database with another application. The table
|
||||
prefix option is called `tbl`.
|
||||
|
||||
> #### Note
|
||||
> The "zerobin_db" model has only been tested with SQLite and MySQL, although it
|
||||
would not be recommended to use SQLite in a production environment. If you gain
|
||||
any experience running ZeroBin on other RDBMS, please let us know.
|
||||
|
||||
For reference or if you want to create the table schema for yourself:
|
||||
|
||||
@@ -66,32 +91,3 @@ For reference or if you want to create the table schema for yourself:
|
||||
vizhash TEXT,
|
||||
postdate INT
|
||||
);
|
||||
|
||||
For Developers
|
||||
--------------
|
||||
If you want to create your own data models, you might want to know how the
|
||||
arrays, that you have to store, look like:
|
||||
|
||||
public function create($pasteid, $paste)
|
||||
{
|
||||
$pasteid = substr(hash('md5', $paste['data']), 0, 16);
|
||||
|
||||
$paste['data'] // text
|
||||
$paste['meta']['postdate'] // int UNIX timestamp
|
||||
$paste['meta']['expire_date'] // int UNIX timestamp
|
||||
$paste['meta']['opendiscussion'] // true (if false it is unset)
|
||||
$paste['meta']['burnafterreading'] // true (if false it is unset; if true, then opendiscussion is unset)
|
||||
}
|
||||
|
||||
public function createComment($pasteid, $parentid, $commentid, $comment)
|
||||
{
|
||||
$pasteid // the id of the paste this comment belongs to
|
||||
$parentid // the id of the parent of this comment, may be the paste id itself
|
||||
$commentid = substr(hash('md5', $paste['data']), 0, 16);
|
||||
|
||||
$comment['data'] // text
|
||||
$comment['meta']['nickname'] // text or null (if anonymous)
|
||||
$comment['meta']['vizhash'] // text or null (if anonymous)
|
||||
$comment['meta']['postdate'] // int UNIX timestamp
|
||||
}
|
||||
|
||||
|
||||
68
README.md
68
README.md
@@ -1,4 +1,4 @@
|
||||
# ZeroBin 0.20
|
||||
# ZeroBin 0.21
|
||||
|
||||
ZeroBin is a minimalist, opensource online pastebin where the server has zero
|
||||
knowledge of pasted data.
|
||||
@@ -12,16 +12,16 @@ without loosing any data.
|
||||
|
||||
## What ZeroBin provides
|
||||
|
||||
- As a server administrator you don't have to worry if your users post content
|
||||
+ As a server administrator you don't have to worry if your users post content
|
||||
that is considered illegal in your country. You have no knowledge of any
|
||||
pastes content. If requested or enforced, you can delete any paste from your
|
||||
system.
|
||||
of the pastes content. If requested or enforced, you can delete any paste from
|
||||
your system.
|
||||
|
||||
- Pastebin like system to store text documents, code samples, etc.
|
||||
+ Pastebin-like system to store text documents, code samples, etc.
|
||||
|
||||
- Encryption of data sent to server, even if it does not provide HTTPS.
|
||||
+ Encryption of data sent to server, even if it does not provide HTTPS.
|
||||
|
||||
- Possibility to set a password which is required to read the paste. It further
|
||||
+ Possibility to set a password which is required to read the paste. It further
|
||||
protects a paste and prevents people stumbling upon your paste's link
|
||||
from being able to read it without the password.
|
||||
|
||||
@@ -43,48 +43,38 @@ without loosing any data.
|
||||
Some features are optional and can be enabled or disabled in the [configuration
|
||||
file](https://github.com/elrido/ZeroBin/wiki/Configuration):
|
||||
|
||||
- Password protection
|
||||
* Password protection
|
||||
|
||||
- Discussions
|
||||
* Discussions
|
||||
|
||||
- Expiration times, including a "forever" and "burn after reading" option
|
||||
* Expiration times, including a "forever" and "burn after reading" option
|
||||
|
||||
- Syntax highlighting using prettify.js, including 4 prettify themes
|
||||
* Markdown format support for HTML formatted pastes
|
||||
|
||||
- Templates: By default there is a bootstrap based and a "classic ZeroBin" theme
|
||||
* Syntax highlighting for source code using prettify.js, including 4 prettify themes
|
||||
|
||||
* File upload support, images get displayed (disabled by default, possibility to adjust size limit)
|
||||
|
||||
* Templates: By default there is a bootstrap CSS and a "classic ZeroBin" theme
|
||||
and it is easy to adapt these to your own websites layout or create your own.
|
||||
|
||||
* Translation system and automatic browser language detection (if enabled in browser)
|
||||
|
||||
* Language selection (disabled by default, as it uses a session cookie)
|
||||
|
||||
## Further resources
|
||||
|
||||
- [Installation guide](https://github.com/elrido/ZeroBin/wiki/Installation)
|
||||
* [Installation guide](https://github.com/elrido/ZeroBin/wiki/Installation)
|
||||
|
||||
- [Configuration guide](https://github.com/elrido/ZeroBin/wiki/Configuration)
|
||||
* [Upgrading from 0.19 Alpha](https://github.com/elrido/ZeroBin/wiki/Upgrading-from-ZeroBin-0.19-Alpha)
|
||||
|
||||
- [Developer guide](https://github.com/elrido/ZeroBin/wiki/Development)
|
||||
* [Configuration guide](https://github.com/elrido/ZeroBin/wiki/Configuration)
|
||||
|
||||
* [Templates](https://github.com/elrido/ZeroBin/wiki/Templates)
|
||||
|
||||
* [Translation guide](https://github.com/elrido/ZeroBin/wiki/Translation)
|
||||
|
||||
* [Developer guide](https://github.com/elrido/ZeroBin/wiki/Development)
|
||||
|
||||
Run into any issues? Have ideas for further developments? Please
|
||||
[report](https://github.com/elrido/ZeroBin/issues) them!
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
48
cfg/conf.ini
48
cfg/conf.ini
@@ -5,7 +5,7 @@
|
||||
; @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
; @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
; @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
; @version 0.20
|
||||
; @version 0.21
|
||||
|
||||
[main]
|
||||
; enable or disable the discussion feature, defaults to true
|
||||
@@ -14,17 +14,21 @@ discussion = true
|
||||
; preselect the discussion feature, defaults to false
|
||||
opendiscussion = false
|
||||
|
||||
; enable or disable syntax highlighting, defaults to true
|
||||
syntaxhighlighting = true
|
||||
; enable or disable the password feature, defaults to true
|
||||
password = true
|
||||
|
||||
; (optional) set a syntax highlighting theme, as found in css/prettify/
|
||||
; syntaxhighlightingtheme = "sons-of-obsidian"
|
||||
; enable or disable the file upload feature, defaults to false
|
||||
fileupload = false
|
||||
|
||||
; preselect the burn-after-reading feature, defaults to false
|
||||
burnafterreadingselected = false
|
||||
|
||||
; enable or disable the password feature, defaults to true
|
||||
password = true
|
||||
; which display mode to preselect by default, defaults to "plaintext"
|
||||
; make sure the value exists in [formatter_options]
|
||||
defaultformatter = "plaintext"
|
||||
|
||||
; (optional) set a syntax highlighting theme, as found in css/prettify/
|
||||
; syntaxhighlightingtheme = "sons-of-obsidian"
|
||||
|
||||
; size limit per paste or comment in bytes, defaults to 2 Mibibytes
|
||||
sizelimit = 2097152
|
||||
@@ -39,6 +43,11 @@ template = "bootstrap"
|
||||
; use "1.7" if you are upgrading from a ZeroBin Alpha 0.19 installation
|
||||
base64version = "2.1.9"
|
||||
|
||||
; by default ZeroBin will guess the visitors language based on the browsers
|
||||
; settings. Optionally you can enable the language selection menu, which uses
|
||||
; a session cookie to store the choice until the browser is closed.
|
||||
languageselection = false
|
||||
|
||||
[expire]
|
||||
; expire value that is selected per default
|
||||
; make sure the value exists in [expire_options]
|
||||
@@ -57,22 +66,22 @@ default = "1week"
|
||||
1year = 31536000
|
||||
never = 0
|
||||
|
||||
[expire_labels]
|
||||
; descriptive labels for the expiration times
|
||||
; must match those in [expire_options]
|
||||
5min = "5 minutes"
|
||||
10min = "10 minutes"
|
||||
1hour = "1 hour"
|
||||
1day = "1 day"
|
||||
1week = "1 week"
|
||||
1month = "1 month"
|
||||
1year = "1 year"
|
||||
never = "Never"
|
||||
[formatter_options]
|
||||
; Set available formatters, their order and their labels
|
||||
plaintext = "Plain Text"
|
||||
syntaxhighlighting = "Source Code"
|
||||
markdown = "Markdown"
|
||||
|
||||
[traffic]
|
||||
; time limit between calls from the same IP address in seconds
|
||||
; Set this to 0 to disable rate limiting.
|
||||
limit = 10
|
||||
|
||||
; (optional) if your website runs behind a reverse proxy or load balancer,
|
||||
; set the HTTP header containing the visitors IP address, i.e. X_FORWARDED_FOR
|
||||
; header = "X_FORWARDED_FOR"
|
||||
|
||||
; directory to store the traffic limits in
|
||||
dir = PATH "data"
|
||||
|
||||
[model]
|
||||
@@ -99,5 +108,4 @@ dir = PATH "data"
|
||||
;dsn = "sqlite:" PATH "data/db.sq3"
|
||||
;usr = null
|
||||
;pwd = null
|
||||
;opt[12] = true ; PDO::ATTR_PERSISTENT
|
||||
|
||||
;opt[12] = true ; PDO::ATTR_PERSISTENT
|
||||
11
css/bootstrap/bootstrap-3.3.5.css
vendored
11
css/bootstrap/bootstrap-3.3.5.css
vendored
File diff suppressed because one or more lines are too long
@@ -1,8 +1,41 @@
|
||||
/* ZeroBin 0.20 - http://sebsauvage.net/wiki/doku.php?id=php:zerobin */
|
||||
/* ZeroBin 0.21 - http://sebsauvage.net/wiki/doku.php?id=php:zerobin */
|
||||
|
||||
|
||||
body {
|
||||
padding: 70px 0 30px 0;
|
||||
padding: 0 0 30px;
|
||||
}
|
||||
|
||||
body.navbar-spacing {
|
||||
padding-top: 70px;
|
||||
}
|
||||
|
||||
.navbar-nav {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > label, .dropdown-menu > li > div {
|
||||
clear: both;
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
line-height: 1.42857;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > label {
|
||||
color: #333;
|
||||
padding: 3px 20px 3px 40px;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > div {
|
||||
color: #777;
|
||||
padding: 3px 20px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#image img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#deletelink {
|
||||
@@ -21,8 +54,20 @@ body {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
#comments, #comments button {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.comment {
|
||||
border-left: 1px solid #ccc;
|
||||
padding: 5px 0 5px 5px;
|
||||
padding: 5px 0 5px 10px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
footer h4 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 {
|
||||
list-style-type: decimal !important;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* ZeroBin 0.20 - http://sebsauvage.net/wiki/doku.php?id=php:zerobin */
|
||||
/* ZeroBin 0.21 - http://sebsauvage.net/wiki/doku.php?id=php:zerobin */
|
||||
|
||||
|
||||
/* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.
|
||||
@@ -18,16 +18,16 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 15px;
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
}
|
||||
|
||||
a { color: #0f388f; }
|
||||
|
||||
h1 {
|
||||
a { color: #0f388f; cursor:pointer; }
|
||||
|
||||
h1.title {
|
||||
font-size: 3.5em;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
@@ -36,7 +36,7 @@ h1 {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
h1:before {
|
||||
h1.title:before {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
color: rgba(255,255,255,0.15);
|
||||
@@ -45,7 +45,7 @@ h1:before {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
h2 {
|
||||
h2.title {
|
||||
color: #000;
|
||||
font-size: 1em;
|
||||
display: inline;
|
||||
@@ -54,18 +54,17 @@ h2 {
|
||||
position: relative;
|
||||
bottom: 8px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
|
||||
h3.title {
|
||||
color: #94a3b4;
|
||||
font-size: 0.7em;
|
||||
display: inline;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
#aboutbox {
|
||||
font-size: 1.2em;
|
||||
color: #94a3b4;
|
||||
padding: 4px 8px 4px 16px;
|
||||
position: relative;
|
||||
@@ -77,15 +76,12 @@ h3 {
|
||||
|
||||
#aboutbox a { color: #94a3b4; }
|
||||
|
||||
#message, #cleartext, .replymessage {
|
||||
#message, #cleartext, #prettymessage, #attachment, .replymessage {
|
||||
clear: both;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
white-space: pre-wrap;
|
||||
font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace;
|
||||
font-size: 9pt;
|
||||
border: 1px solid #28343F;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
@@ -94,6 +90,17 @@ h3 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#message, .replymessage {
|
||||
padding: 5px;
|
||||
white-space: pre-wrap;
|
||||
font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace;
|
||||
}
|
||||
|
||||
#image img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#status {
|
||||
clear: both;
|
||||
padding: 5px 10px;
|
||||
@@ -119,7 +126,7 @@ h3 {
|
||||
|
||||
#copyhint { color: #666; font-size: 0.85em; }
|
||||
|
||||
button, .button, #expiration {
|
||||
button, .button {
|
||||
color: #fff;
|
||||
background-color: #323b47;
|
||||
background-repeat: no-repeat;
|
||||
@@ -127,7 +134,7 @@ button, .button, #expiration {
|
||||
padding: 4px 8px;
|
||||
font-size: 1em;
|
||||
margin-right: 5px;
|
||||
display: inline;
|
||||
display: inline-block;
|
||||
background-image: linear-gradient(bottom, #323b47 0, #51606e 100%);
|
||||
background-image: -o-linear-gradient(bottom, #323b47 0, #51606e 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #323b47 0, #51606e 100%);
|
||||
@@ -178,7 +185,7 @@ button img {
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
#expiration, #rawtextbutton, #burnafterreadingoption, #opendisc {
|
||||
.button {
|
||||
background-color: #414d5a;
|
||||
padding: 6px 8px;
|
||||
margin: 0 5px 0 0;
|
||||
@@ -186,14 +193,14 @@ button img {
|
||||
bottom: 1px; /* WTF ? Why is this shifted by 1 pixel ? */
|
||||
}
|
||||
|
||||
#expiration select {
|
||||
.button select {
|
||||
color: #eee;
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
#expiration select option {
|
||||
.button select option {
|
||||
color:#eee;
|
||||
background: #414d5a;
|
||||
}
|
||||
@@ -202,7 +209,7 @@ button img {
|
||||
padding: 1px 0 1px 0;
|
||||
}
|
||||
|
||||
#remainingtime {
|
||||
#remainingtime, #password {
|
||||
color: #94a3b4;
|
||||
display: inline;
|
||||
font-size: 0.85em;
|
||||
@@ -234,7 +241,7 @@ input {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.nonworking {
|
||||
#image, .nonworking {
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
width: 100%;
|
||||
@@ -244,7 +251,7 @@ input {
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
padding: 5px;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.hidden { display: none !important; }
|
||||
@@ -279,7 +286,7 @@ input {
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
h4.title {
|
||||
font-size: 1.2em;
|
||||
color: #94a3b4;
|
||||
font-style: italic;
|
||||
@@ -386,3 +393,37 @@ img.vizhash {
|
||||
color: #000000;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#cleartext {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#cleartext * {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#cleartext ol {
|
||||
list-style: auto;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#cleartext ul {
|
||||
list-style: disc;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#cleartext h1, #cleartext h2, #cleartext h3, #cleartext h4, #cleartext h5, #cleartext h6 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#cleartext h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
#cleartext h2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
#cleartext h3 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
139
i18n/de.json
Normal file
139
i18n/de.json
Normal file
@@ -0,0 +1,139 @@
|
||||
{
|
||||
"en": "de",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Diesen Text gibt es nicht, er ist abgelaufen oder wurde gelöscht.",
|
||||
"ZeroBin requires php 5.2.6 or above to work. Sorry.":
|
||||
"ZeroBin benötigt PHP 5.2.6 oder höher, um zu funktionieren. Sorry.",
|
||||
"ZeroBin requires configuration section [%s] to be present in configuration file.":
|
||||
"ZeroBin benötigt den Konfigurationsabschnitt [%s] in der Konfigurationsdatei um zu funktionieren.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Bitte warte %d Sekunden zwischen dem Absenden.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Texte sind auf %s verschlüsselte Datenmenge beschränkt.",
|
||||
"Invalid data.":
|
||||
"Ungültige Daten.",
|
||||
"You are unlucky. Try again.":
|
||||
"Du hast Pech. Versuchs nochmal.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Fehler beim Speichern des Kommentars. Sorry.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Fehler beim Speichern des Textes. Sorry.",
|
||||
"Invalid paste ID.":
|
||||
"Ungültige Text-ID.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Text ist kein \"Einmal\"-Typ.",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Falscher Lösch-Code. Text wurde nicht gelöscht.",
|
||||
"Paste was properly deleted.":
|
||||
"Text wurde erfolgreich gelöscht.",
|
||||
"ZeroBin": "ZeroBin",
|
||||
"ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://github.com/elrido/ZeroBin/wiki\">project page</a>.":
|
||||
"ZeroBin ist ein minimalistischer, quelloffener \"Pastebin\"-artiger Dienst, bei dem der Server keinerlei Kenntnis der Inhalte hat. Die Daten werden <i>im Browser</i> mit 256 Bit AES ver- und entschlüsselt. Weitere Informationen sind auf der <a href=\"https://github.com/elrido/ZeroBin/wiki\">Projektseite</a> zu finden.",
|
||||
"Because ignorance is bliss":
|
||||
"Unwissenheit ist ein Segen",
|
||||
"Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.":
|
||||
"Javascript ist eine Voraussetzung, um ZeroBin zu nutzen.<br />Bitte entschuldige die Unannehmlichkeiten.",
|
||||
"ZeroBin requires a modern browser to work.":
|
||||
"ZeroBin setzt einen modernen Browser voraus, um funktionieren zu können.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Du benutzt immer noch den Internet Explorer? Tu Dir einen Gefallen und wechsle zu einem moderneren Browser:",
|
||||
"New":
|
||||
"Neu",
|
||||
"Send":
|
||||
"Senden",
|
||||
"Clone":
|
||||
"Klonen",
|
||||
"Raw text":
|
||||
"Reiner Text",
|
||||
"Expires":
|
||||
"Ablaufzeit",
|
||||
"Burn after reading":
|
||||
"Einmal-Text",
|
||||
"Open discussion":
|
||||
"Diskussion eröffnen",
|
||||
"Password (recommended)":
|
||||
"Passwort (empfohlen)",
|
||||
"Discussion":
|
||||
"Diskussion",
|
||||
"Toggle navigation":
|
||||
"Navigation umschalten",
|
||||
"%d seconds": ["%d Sekunde", "%d Sekunden"],
|
||||
"%d minutes": ["%d Minute", "%d Minuten"],
|
||||
"%d hours": ["%d Stunde", "%d Stunden"],
|
||||
"%d days": ["%d Tag", "%d Tage"],
|
||||
"%d weeks": ["%d Woche", "%d Wochen"],
|
||||
"%d months": ["%d Monat", "%d Monate"],
|
||||
"%d years": ["%d Jahr", "%d Jahre"],
|
||||
"Never":
|
||||
"Nie",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Hinweis: Dies ist ein Versuchsdienst. Daten können jederzeit gelöscht werden. Kätzchen werden sterben wenn Du diesen Dienst missbrauchst.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Dieses Dokument läuft in einer Sekunde ab.", "Dieses Dokument läuft in %d Sekunden ab."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Dieses Dokument läuft in einer Minute ab.", "Dieses Dokument läuft in %d Minuten ab."],
|
||||
"This document will expire in %d hours.":
|
||||
["Dieses Dokument läuft in einer Stunde ab.", "Dieses Dokument läuft in %d Stunden ab."],
|
||||
"This document will expire in %d days.":
|
||||
["Dieses Dokument läuft in einem Tag ab.", "Dieses Dokument läuft in %d Tagen ab."],
|
||||
"This document will expire in %d months.":
|
||||
["Dieses Dokument läuft in einem Monat ab.", "Dieses Dokument läuft in %d Monaten ab."],
|
||||
"Please enter the password for this paste:":
|
||||
"Bitte gib das Passwort für diesen Text ein:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Konnte Daten nicht entschlüsseln (Falscher Schlüssel?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Konnte den Text nicht löschen, er wurde nicht im Einmal-Modus gespeichert.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"DIESER TEXT IST NUR FÜR DICH GEDACHT. Schliesse das Fenster nicht, diese Nachricht kann nur einmal geöffnet werden.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Konnte Kommentar nicht entschlüsseln; Falscher Schlüssel?",
|
||||
"Reply":
|
||||
"Antworten",
|
||||
"Anonymous":
|
||||
"Anonym",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Anonymer Avatar (Vizhash der IP-Addresse)",
|
||||
"Add comment":
|
||||
"Kommentar hinzufügen",
|
||||
"Optional nickname...":
|
||||
"Optionales Pseudonym...",
|
||||
"Post comment":
|
||||
"Kommentar absenden",
|
||||
"Sending comment...":
|
||||
"Sende Kommentar...",
|
||||
"Comment posted.":
|
||||
"Kommentar gesendet.",
|
||||
"Could not refresh display: %s":
|
||||
"Konnte Ansicht nicht aktualisieren: %s",
|
||||
"unknown status":
|
||||
"Unbekannter Grund",
|
||||
"server error or not responding":
|
||||
"Fehler auf dem Server oder keine Antwort vom Server",
|
||||
"Could not post comment: %s":
|
||||
"Konnte Kommentar nicht senden: %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Sende Text (Bitte bewege Deine Maus um die Entropie zu erhöhen)...",
|
||||
"Sending paste...":
|
||||
"Sende Text...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Dein Text ist unter <a id=\"pasteurl\" href=\"%s\">%s</a> zu finden <span id=\"copyhint\">(Drücke [Strg]+[c] um den Link zu kopieren)</span>",
|
||||
"Delete data":
|
||||
"Lösche Daten",
|
||||
"Could not create paste: %s":
|
||||
"Konnte Text nicht erstellen: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Konnte Text nicht entschlüsseln: Der Schlüssel fehlt in der Adresse (Hast Du eine Umleitung oder einen URL-Verkürzer benutzt, der Teile der Adresse entfernt?)",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Nur Text",
|
||||
"Source Code": "Quellcode",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Anhang herunterladen",
|
||||
"Cloned file attached.": "Kopierte Datei angehängt.",
|
||||
"Attach a file": "Datei anhängen",
|
||||
"Remove attachment": "Anhang entfernen",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Dein Browser unterstützt das hochladen von verschlüsselten Dateien nicht. Bitte verwende einen neueren Browser.",
|
||||
"Invalid attachment.": "Ungültiger Datei-Anhang.",
|
||||
"Options": "Optionen"
|
||||
}
|
||||
148
i18n/fr.json
Normal file
148
i18n/fr.json
Normal file
@@ -0,0 +1,148 @@
|
||||
{
|
||||
"en": "fr",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Le paste n'existe pas, a expiré, ou a été supprimé.",
|
||||
"ZeroBin requires php 5.2.6 or above to work. Sorry.":
|
||||
"Désolé, ZeroBin nécessite php 5.2.6 ou supérieur pour fonctionner.",
|
||||
"ZeroBin requires configuration section [%s] to be present in configuration file.":
|
||||
"ZeroBin a besoin de la section de configuration [%s] dans le fichier de configuration pour fonctionner.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Merci d'attendre %d secondes entre chaque publication.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Le paste est limité à %s de données chiffrées.",
|
||||
"Invalid data.":
|
||||
"Données invalides.",
|
||||
"You are unlucky. Try again.":
|
||||
"Pas de chance. Essayez encore.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Erreur lors de la sauvegarde du commentaire.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Erreur lors de la sauvegarde du paste. Désolé.",
|
||||
"Invalid paste ID.":
|
||||
"ID du paste invalide.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Le paste n'est pas de type \"Effacer après lecture\".",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Jeton de suppression incorrect. Le paste n'a pas été supprimé.",
|
||||
"Paste was properly deleted.":
|
||||
"Le paste a été correctement supprimé.",
|
||||
"ZeroBin": "ZeroBin",
|
||||
"ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://github.com/elrido/ZeroBin/wiki\">project page</a>.":
|
||||
"Zerobin est un 'pastebin' (ou gestionnaire d'extraits de texte et de code source) minimaliste et open source, dans lequel le serveur n'a aucune connaissance des données envoyées. Les données sont chiffrées/déchiffrées <i>dans le navigateur</i> par un chiffrage AES 256 bits. Plus d'informations sur <a href=\"https://github.com/elrido/ZeroBin/wiki\">la page du projet</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Parce que l'ignorance est le bonheur",
|
||||
"Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.":
|
||||
"Javascript est requis pour faire fonctionner ZeroBin. <br />Désolé pour cet inconvénient.",
|
||||
"ZeroBin requires a modern browser to work.":
|
||||
"ZeroBin nécessite un navigateur moderne pour fonctionner.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Encore sur Internet Explorer ? Faites-vous une faveur, passez à un navigateur moderne :",
|
||||
"New":
|
||||
"Nouveau",
|
||||
"Send":
|
||||
"Envoyer",
|
||||
"Clone":
|
||||
"Cloner",
|
||||
"Raw text":
|
||||
"Texte brut",
|
||||
"Expires":
|
||||
"Expire",
|
||||
"Burn after reading":
|
||||
"Effacer après lecture",
|
||||
"Open discussion":
|
||||
"Autoriser la discussion",
|
||||
"Password (recommended)":
|
||||
"Mot de passe (recommandé)",
|
||||
"Discussion":
|
||||
"Discussion",
|
||||
"Toggle navigation":
|
||||
"Basculer la navigation",
|
||||
"%d seconds": ["%d seconde", "%d secondes"],
|
||||
"%d minutes": ["%d minute", "%d minutes"],
|
||||
"%d hours": ["%d heure", "%d heures"],
|
||||
"%d days": ["%d jour", "%d jours"],
|
||||
"%d weeks": ["%d semaine", "%d semaines"],
|
||||
"%d months": ["%d mois", "%d mois"],
|
||||
"%d years": ["%d an", "%d ans"],
|
||||
"Never":
|
||||
"Jamais",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Note : Ceci est un service de test : les données peuvent être supprimées à tout moment. Des chatons mourront si vous utilisez ce service de manière abusive.",
|
||||
"This document will expire in %d seconds.":
|
||||
["Ce document expirera dans %d seconde.", "Ce document expirera dans %d secondes."],
|
||||
"This document will expire in %d minutes.":
|
||||
["Ce document expirera dans %d minute.", "Ce document expirera dans %d minutes."],
|
||||
"This document will expire in %d hours.":
|
||||
["Ce document expirera dans %d heure.", "Ce document expirera dans %d heures."],
|
||||
"This document will expire in %d days.":
|
||||
["Ce document expirera dans %d jour.", "Ce document expirera dans %d jours."],
|
||||
"This document will expire in %d months.":
|
||||
["Ce document expirera dans %d mois.", "Ce document expirera dans %d mois."],
|
||||
"Please enter the password for this paste:":
|
||||
"Entrez le mot de passe pour ce paste:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Impossible de déchiffrer les données (mauvaise clé ?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Impossible de supprimer le paste, car il n'a pas été stoclé en mode \"Effacer après lecture\".",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"POUR VOS YEUX UNIQUEMENT. Ne fermez pas cette fenêtre, ce paste ne pourra plus être affiché.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Umpossible de déchiffrer le commentaire ; mauvaise clé ?",
|
||||
"Reply":
|
||||
"Répondre",
|
||||
"Anonymous":
|
||||
"Anonyme",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Avatar anonyme (Vizhash de l'adresse IP)",
|
||||
"Add comment":
|
||||
"Ajouter un commentaire",
|
||||
"Optional nickname...":
|
||||
"Pseudonyme optionnel...",
|
||||
"Post comment":
|
||||
"Poster le commentaire",
|
||||
"Sending comment...":
|
||||
"Envoi du commentaire...",
|
||||
"Comment posted.":
|
||||
"Commentaire posté.",
|
||||
"Could not refresh display: %s":
|
||||
"Impossible de rafraichir l'affichage : %s",
|
||||
"unknown status":
|
||||
"Statut inconnu",
|
||||
"server error or not responding":
|
||||
"Le serveur ne répond pas ou a rencontré une erreur",
|
||||
"Could not post comment: %s":
|
||||
"Impossible de poster le commentaire : %s",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Envoi du paste (Merci de bouger votre souris pour plus d'entropie)...",
|
||||
"Sending paste...":
|
||||
"Envoi du paste...",
|
||||
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
|
||||
"Votre paste est disponible à l'adresse <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Appuyez sur [Ctrl]+[c] pour copier)</span>",
|
||||
"Delete data":
|
||||
"Supprimer les données du paste",
|
||||
"Could not create paste: %s":
|
||||
"Impossible de créer le paste : %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Impossible de déchiffrer le paste : Clé de déchiffrage manquante dans l'URL (Avez-vous utilisé un redirecteur ou un site de réduction d'URL qui supprime une partie de l'URL ?)",
|
||||
"B": "o",
|
||||
"KiB": "Kio",
|
||||
"MiB": "Mio",
|
||||
"GiB": "Gio",
|
||||
"TiB": "Tio",
|
||||
"PiB": "Pio",
|
||||
"EiB": "Eio",
|
||||
"ZiB": "Zio",
|
||||
"YiB": "Yio",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Texte brut",
|
||||
"Source Code": "Code source",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Télécharger la pièce jointe",
|
||||
"Cloned file attached.": "Cloner le fichier attaché.",
|
||||
"Attach a file": "Attacher un fichier ",
|
||||
"Remove attachment": "Enlever l'attachement",
|
||||
"Your browser does not support uploading encrypted files. Please use a newer browser.":
|
||||
"Votre navigateur ne supporte pas l'envoi de fichiers chiffrés. Merci d'utiliser un navigateur plus récent.",
|
||||
"Invalid attachment.": "Attachement invalide.",
|
||||
"Options": "Options"
|
||||
}
|
||||
181
i18n/languages.json
Normal file
181
i18n/languages.json
Normal file
@@ -0,0 +1,181 @@
|
||||
{
|
||||
"ab": ["аҧсуа бызшәа", "Abkhaz"],
|
||||
"aa": ["Afaraf", "Afar"],
|
||||
"af": ["Afrikaans", "Afrikaans"],
|
||||
"ak": ["Akan", "Akan"],
|
||||
"sq": ["Shqip", "Albanian"],
|
||||
"am": ["አማርኛ", "Amharic"],
|
||||
"ar": ["العربية", "Arabic"],
|
||||
"an": ["aragonés", "Aragonese"],
|
||||
"hy": ["Հայերեն", "Armenian"],
|
||||
"as": ["অসমীয়া", "Assamese"],
|
||||
"ac": ["Ástralic", "Australian"],
|
||||
"av": ["авар мацӀ", "Avaric"],
|
||||
"ae": ["avesta", "Avestan"],
|
||||
"ay": ["aymar aru", "Aymara"],
|
||||
"az": ["azərbaycan dili", "Azerbaijani"],
|
||||
"bm": ["bamanankan", "Bambara"],
|
||||
"ba": ["башҡорт теле", "Bashkir"],
|
||||
"eu": ["euskara", "Basque"],
|
||||
"be": ["беларуская мова", "Belarusian"],
|
||||
"bn": ["বাংলা", "Bengali"],
|
||||
"bh": ["भोजपुरी", "Bihari"],
|
||||
"bi": ["Bislama", "Bislama"],
|
||||
"bs": ["bosanski jezik", "Bosnian"],
|
||||
"br": ["brezhoneg", "Breton"],
|
||||
"bg": ["български език", "Bulgarian"],
|
||||
"my": ["ဗမာစာ", "Burmese"],
|
||||
"ca": ["català", "Catalan"],
|
||||
"ch": ["Chamoru", "Chamorro"],
|
||||
"ce": ["нохчийн мотт", "Chechen"],
|
||||
"ny": ["chiCheŵa", "Chichewa"],
|
||||
"zh": ["中文", "Chinese"],
|
||||
"cv": ["чӑваш чӗлхи", "Chuvash"],
|
||||
"kw": ["Kernewek", "Cornish"],
|
||||
"co": ["corsu", "Corsican"],
|
||||
"cr": ["ᓀᐦᐃᔭᐍᐏᐣ", "Cree"],
|
||||
"hr": ["hrvatski jezik", "Croatian"],
|
||||
"cs": ["čeština", "Czech"],
|
||||
"da": ["dansk", "Danish"],
|
||||
"dv": ["ދިވެހި", "Divehi"],
|
||||
"nl": ["Nederlands", "Dutch"],
|
||||
"dz": ["རྫོང་ཁ", "Dzongkha"],
|
||||
"en": ["English", "English"],
|
||||
"eo": ["Esperanto", "Esperanto"],
|
||||
"et": ["eesti", "Estonian"],
|
||||
"ee": ["Eʋegbe", "Ewe"],
|
||||
"fo": ["føroyskt", "Faroese"],
|
||||
"fj": ["vosa Vakaviti", "Fijian"],
|
||||
"fi": ["suomi", "Finnish"],
|
||||
"fr": ["français", "French"],
|
||||
"ff": ["Fulfulde", "Fula"],
|
||||
"gl": ["galego", "Galician"],
|
||||
"ka": ["ქართული", "Georgian"],
|
||||
"de": ["Deutsch", "German"],
|
||||
"el": ["ελληνικά", "Greek"],
|
||||
"gn": ["Avañe'ẽ", "Guaraní"],
|
||||
"gu": ["ગુજરાતી", "Gujarati"],
|
||||
"ht": ["Kreyòl ayisyen", "Haitian"],
|
||||
"ha": ["هَوُسَ", "Hausa"],
|
||||
"he": ["עברית", "Hebrew"],
|
||||
"hz": ["Otjiherero", "Herero"],
|
||||
"hi": ["हिन्दी", "Hindi"],
|
||||
"ho": ["Hiri Motu", "Hiri Motu"],
|
||||
"hu": ["magyar", "Hungarian"],
|
||||
"ia": ["Interlingua", "Interlingua"],
|
||||
"ie": ["Interlingue", "Interlingue"],
|
||||
"ga": ["Gaeilge", "Irish"],
|
||||
"ig": ["Asụsụ Igbo", "Igbo"],
|
||||
"ik": ["Iñupiaq", "Inupiaq"],
|
||||
"io": ["Ido", "Ido"],
|
||||
"is": ["Íslenska", "Icelandic"],
|
||||
"it": ["italiano", "Italian"],
|
||||
"iu": ["ᐃᓄᒃᑎᑐᑦ", "Inuktitut"],
|
||||
"ja": ["日本語", "Japanese"],
|
||||
"jv": ["basa Jawa", "Javanese"],
|
||||
"kl": ["kalaallisut", "Greenlandic"],
|
||||
"kn": ["ಕನ್ನಡ", "Kannada"],
|
||||
"kr": ["Kanuri", "Kanuri"],
|
||||
"ks": ["कश्मीरी", "Kashmiri"],
|
||||
"kk": ["қазақ тілі", "Kazakh"],
|
||||
"km": ["ខ្មែរ", "Khmer"],
|
||||
"ki": ["Gĩkũyũ", "Kikuyu"],
|
||||
"rw": ["Ikinyarwanda", "Kinyarwanda"],
|
||||
"ky": ["Кыргызча", "Kyrgyz"],
|
||||
"kv": ["коми кыв", "Komi"],
|
||||
"kg": ["Kikongo", "Kongo"],
|
||||
"ko": ["한국어", "Korean"],
|
||||
"ku": ["Kurdî", "Kurdish"],
|
||||
"kj": ["Kuanyama", "Kwanyama"],
|
||||
"la": ["lingua latina", "Latin"],
|
||||
"lb": ["Lëtzebuergesch", "Luxembourgish"],
|
||||
"lg": ["Luganda", "Ganda"],
|
||||
"li": ["Limburgs", "Limburgish"],
|
||||
"ln": ["Lingála", "Lingala"],
|
||||
"lo": ["ພາສາລາວ", "Lao"],
|
||||
"lt": ["lietuvių kalba", "Lithuanian"],
|
||||
"lu": ["Tshiluba", "Luba-Katanga"],
|
||||
"lv": ["latviešu valoda", "Latvian"],
|
||||
"gv": ["Gaelg", "Manx"],
|
||||
"mk": ["македонски јазик", "Macedonian"],
|
||||
"mg": ["fiteny malagasy", "Malagasy"],
|
||||
"ms": ["بهاس ملايو", "Malay"],
|
||||
"ml": ["മലയാളം", "Malayalam"],
|
||||
"mt": ["Malti", "Maltese"],
|
||||
"mi": ["te reo Māori", "Māori"],
|
||||
"mr": ["मराठी", "Marathi"],
|
||||
"mh": ["Kajin M̧ajeļ", "Marshallese"],
|
||||
"mn": ["Монгол хэл", "Mongolian"],
|
||||
"na": ["Ekakairũ Naoero", "Nauru"],
|
||||
"nv": ["Diné bizaad", "Navajo"],
|
||||
"nd": ["isiNdebele", "Northern Ndebele"],
|
||||
"ne": ["नेपाली", "Nepali"],
|
||||
"ng": ["Owambo", "Ndonga"],
|
||||
"no": ["Norsk", "Norwegian"],
|
||||
"ii": ["ꆈꌠ꒿", "Nuosu"],
|
||||
"nr": ["isiNdebele", "Southern Ndebele"],
|
||||
"oc": ["occitan", "Occitan"],
|
||||
"oj": ["ᐊᓂᔑᓈᐯᒧᐎᓐ", "Ojibwe"],
|
||||
"om": ["Afaan Oromoo", "Oromo"],
|
||||
"or": ["ଓଡ଼ିଆ", "Oriya"],
|
||||
"os": ["ирон æвзаг", "Ossetian"],
|
||||
"pa": ["ਪੰਜਾਬੀ", "Punjabi"],
|
||||
"pi": ["पाऴि", "Pāli"],
|
||||
"fa": ["فارسی", "Persian"],
|
||||
"pl": ["polszczyzna", "Polish"],
|
||||
"ps": ["پښتو", "Pashto"],
|
||||
"pt": ["português", "Portuguese"],
|
||||
"qu": ["Runa Simi", "Quechua"],
|
||||
"rm": ["rumantsch grischun", "Romansh"],
|
||||
"rn": ["Ikirundi", "Kirundi"],
|
||||
"ro": ["limba română", "Romanian"],
|
||||
"ru": ["Русский", "Russian"],
|
||||
"sc": ["sardu", "Sardinian"],
|
||||
"sd": ["सिन्धी", "Sindhi"],
|
||||
"se": ["Davvisámegiella", "Northern Sami"],
|
||||
"sm": ["gagana fa'a Samoa", "Samoan"],
|
||||
"sg": ["yângâ tî sängö", "Sango"],
|
||||
"sr": ["српски језик", "Serbian"],
|
||||
"gd": ["Gàidhlig", "Gaelic"],
|
||||
"sn": ["chiShona", "Shona"],
|
||||
"si": ["සිංහල", "Sinhalese"],
|
||||
"sk": ["slovenčina", "Slovak"],
|
||||
"sl": ["slovenščina", "Slovene"],
|
||||
"so": ["Soomaaliga", "Somali"],
|
||||
"st": ["Sesotho", "Southern Sotho"],
|
||||
"es": ["español", "Spanish"],
|
||||
"su": ["Basa Sunda", "Sundanese"],
|
||||
"sw": ["Kiswahili", "Swahili"],
|
||||
"ss": ["SiSwati", "Swati"],
|
||||
"sv": ["svenska", "Swedish"],
|
||||
"ta": ["தமிழ்", "Tamil"],
|
||||
"te": ["తెలుగు", "Telugu"],
|
||||
"tg": ["тоҷикӣ", "Tajik"],
|
||||
"th": ["ไทย", "Thai"],
|
||||
"ti": ["ትግርኛ", "Tigrinya"],
|
||||
"bo": ["བོད་ཡིག", "Tibetan"],
|
||||
"tk": ["Түркмен", "Turkmen"],
|
||||
"tl": ["ᜏᜒᜃᜅ᜔ ᜆᜄᜎᜓᜄ᜔", "Tagalog"],
|
||||
"tn": ["Setswana", "Tswana"],
|
||||
"to": ["faka Tonga", "Tonga"],
|
||||
"tr": ["Türkçe", "Turkish"],
|
||||
"ts": ["Xitsonga", "Tsonga"],
|
||||
"tt": ["татар теле", "Tatar"],
|
||||
"ty": ["Reo Tahiti", "Tahitian"],
|
||||
"ug": ["ئۇيغۇرچە", "Uyghur"],
|
||||
"uk": ["українська мова", "Ukrainian"],
|
||||
"ur": ["اردو", "Urdu"],
|
||||
"uz": ["Oʻzbek", "Uzbek"],
|
||||
"ve": ["Tshivenḓa", "Venda"],
|
||||
"vi": ["Việt Nam", "Vietnamese"],
|
||||
"vo": ["Volapük", "Volapük"],
|
||||
"wa": ["walon", "Walloon"],
|
||||
"cy": ["Cymraeg", "Welsh"],
|
||||
"wo": ["Wollof", "Wolof"],
|
||||
"fy": ["Frysk", "Western Frisian"],
|
||||
"xh": ["isiXhosa", "Xhosa"],
|
||||
"yi": ["ייִדיש", "Yiddish"],
|
||||
"yo": ["Yorùbá", "Yoruba"],
|
||||
"za": ["Saɯ cueŋƅ", "Zhuang"],
|
||||
"zu": ["isiZulu", "Zulu"]
|
||||
}
|
||||
139
i18n/pl.json
Normal file
139
i18n/pl.json
Normal file
@@ -0,0 +1,139 @@
|
||||
{
|
||||
"en": "pl",
|
||||
"Paste does not exist, has expired or has been deleted.":
|
||||
"Wklejka nie istnieje, wygasła albo została usunięta.",
|
||||
"ZeroBin requires php 5.2.6 or above to work. Sorry.":
|
||||
"ZeroBin wymaga PHP w wersji 5.2.6 lub nowszej, sorry.",
|
||||
"ZeroBin requires configuration section [%s] to be present in configuration file.":
|
||||
"ZeroBin wymaga obecności sekcji [%s] w pliku konfiguracyjnym.",
|
||||
"Please wait %d seconds between each post.":
|
||||
"Poczekaj %d sekund pomiędzy każdą wklejką.",
|
||||
"Paste is limited to %s of encrypted data.":
|
||||
"Wklejka jest limitowana do %s zaszyfrowanych danych.",
|
||||
"Invalid data.":
|
||||
"Nieprawidłowe dane.",
|
||||
"You are unlucky. Try again.":
|
||||
"Miałeś pecha. Spróbuj ponownie.",
|
||||
"Error saving comment. Sorry.":
|
||||
"Błąd przy zapisywaniu komentarza, sorry.",
|
||||
"Error saving paste. Sorry.":
|
||||
"Błąd przy zapisywaniu wklejki, sorry.",
|
||||
"Invalid paste ID.":
|
||||
"Nieprawidłowe ID wklejki.",
|
||||
"Paste is not of burn-after-reading type.":
|
||||
"Ta wklejka nie ulega autodestrukcji po przeczytaniu.",
|
||||
"Wrong deletion token. Paste was not deleted.":
|
||||
"Nieprawidłowy token usuwania. Wklejka nie została usunięta.",
|
||||
"Paste was properly deleted.":
|
||||
"Wklejka usunięta poprawnie.",
|
||||
"ZeroBin": "ZeroBin",
|
||||
"ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://github.com/elrido/ZeroBin/wiki\">project page</a>.":
|
||||
"ZeroBin jest minimalistycznym, otwartoźródłowym serwisem typu pastebin, w którym serwer nie ma jakichkolwiek informacji o tym, co jest wklejane. Dane są szyfrowane i deszyfrowane <i>w przeglądarce</i> z użyciem 256-bitowego klucza AES. Więcej informacji na <a href=\"https://github.com/elrido/ZeroBin/wiki\">stronie projektu</a>.",
|
||||
"Because ignorance is bliss":
|
||||
"Ponieważ ignorancja jest cnotą",
|
||||
"Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.":
|
||||
"Do działania ZeroBina jest wymagany JavaScript. Przepraszamy za tę niedogodność.",
|
||||
"ZeroBin requires a modern browser to work.":
|
||||
"ZeroBin wymaga do działania nowoczesnej przeglądarki.",
|
||||
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
|
||||
"Cały czas używasz Internet Explorera? Zrób sobie przysługę, przesiądź się na nowoczesną przeglądarkę:",
|
||||
"New":
|
||||
"Nowa",
|
||||
"Send":
|
||||
"Wyślij",
|
||||
"Clone":
|
||||
"Sklonuj",
|
||||
"Raw text":
|
||||
"Czysty tekst",
|
||||
"Expires":
|
||||
"Wygasa",
|
||||
"Burn after reading":
|
||||
"Zniszcz po przeczytaniu",
|
||||
"Open discussion":
|
||||
"Otwarta dyskusja",
|
||||
"Password (recommended)":
|
||||
"Hasło (zalecane)",
|
||||
"Discussion":
|
||||
"Dyskusja",
|
||||
"Toggle navigation":
|
||||
"Przełącz nawigację",
|
||||
"%d seconds": ["%d second", "%d second", "%d second"],
|
||||
"%d minutes": ["%d minut", "%d minut", "%d minut"],
|
||||
"%d hours": ["%d godzina", "%d godzina", "%d godzina"],
|
||||
"%d days": ["%d dzień", "%d dzień", "%d dzień"],
|
||||
"%d weeks": ["%d tydzień", "%d tydzień", "%d tydzień"],
|
||||
"%d months": ["%d miesiąc", "%d miesiąc", "%d miesiąc"],
|
||||
"%d years": ["%d rok", "%d rok", "%d rok"],
|
||||
"Never":
|
||||
"Nigdy",
|
||||
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
|
||||
"Notka: To jest usługa testowa. Dane mogą zostać usunięte w dowolnym momencie. Kociątka umrą, jeśli nadużyjesz tej usługi.",
|
||||
"This document will expire in %d seconds.":
|
||||
["This document will expire in %d second.", "This document will expire in %d seconds."],
|
||||
"This document will expire in %d minutes.":
|
||||
["This document will expire in %d minute.", "This document will expire in %d minutes."],
|
||||
"This document will expire in %d hours.":
|
||||
["This document will expire in %d hour.", "This document will expire in %d hours."],
|
||||
"This document will expire in %d days.":
|
||||
["This document will expire in %d day.", "This document will expire in %d days."],
|
||||
"This document will expire in %d months.":
|
||||
["This document will expire in %d month.", "This document will expire in %d months."],
|
||||
"Please enter the password for this paste:":
|
||||
"Please enter the password for this paste:",
|
||||
"Could not decrypt data (Wrong key?)":
|
||||
"Could not decrypt data (Wrong key?)",
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.":
|
||||
"Could not delete the paste, it was not stored in burn after reading mode.",
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
|
||||
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.",
|
||||
"Could not decrypt comment; Wrong key?":
|
||||
"Could not decrypt comment; Wrong key?",
|
||||
"Reply":
|
||||
"Reply",
|
||||
"Anonymous":
|
||||
"Anonymous",
|
||||
"Anonymous avatar (Vizhash of the IP address)":
|
||||
"Anonymous avatar (Vizhash of the IP address)",
|
||||
"Add comment":
|
||||
"Add comment",
|
||||
"Optional nickname...":
|
||||
"Optional nickname...",
|
||||
"Post comment":
|
||||
"Post comment",
|
||||
"Sending comment...":
|
||||
"Sending comment...",
|
||||
"Comment posted.":
|
||||
"Comment posted.",
|
||||
"Could not refresh display: %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",
|
||||
"Sending paste (Please move your mouse for more entropy)...":
|
||||
"Sending paste (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>",
|
||||
"Delete data":
|
||||
"Delete data",
|
||||
"Could not create paste: %s":
|
||||
"Could not create paste: %s",
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
|
||||
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)",
|
||||
"Format": "Format",
|
||||
"Plain Text": "Plain Text",
|
||||
"Source Code": "Source Code",
|
||||
"Markdown": "Markdown",
|
||||
"Download attachment": "Download attachment",
|
||||
"Cloned file attached.": "Cloned file attached.",
|
||||
"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.",
|
||||
"Invalid attachment.": "Invalid attachment.",
|
||||
"Options": "Options"
|
||||
}
|
||||
@@ -7,11 +7,12 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
// change this, if your php files and data is outside of your webservers document root
|
||||
define('PATH', '');
|
||||
|
||||
define('PUBLIC_PATH', dirname(__FILE__));
|
||||
require PATH . 'lib/auto.php';
|
||||
new zerobin;
|
||||
|
||||
1296
js/showdown.js
Normal file
1296
js/showdown.js
Normal file
File diff suppressed because it is too large
Load Diff
1869
js/zerobin.js
1869
js/zerobin.js
File diff suppressed because it is too large
Load Diff
357
lib/RainTPL.php
357
lib/RainTPL.php
@@ -84,7 +84,7 @@ class RainTPL{
|
||||
|
||||
/**
|
||||
* Check template
|
||||
*
|
||||
*
|
||||
* true: checks template update time, if changed it compile them
|
||||
* false: loads the compiled template. Set false if server doesn't have write permission for cache_directory.
|
||||
*
|
||||
@@ -133,7 +133,7 @@ class RainTPL{
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $tpl = array(); //
|
||||
protected $tpl = array(); //
|
||||
|
||||
/**
|
||||
* static cache enabled / disabled
|
||||
@@ -154,7 +154,7 @@ class RainTPL{
|
||||
*
|
||||
* @var array the file
|
||||
*/
|
||||
protected static $config_name_sum = array();
|
||||
protected static $config_name_sum = array();
|
||||
|
||||
// -------------------------
|
||||
|
||||
@@ -207,41 +207,41 @@ class RainTPL{
|
||||
}
|
||||
|
||||
// Cache is off and, return_string is false
|
||||
// Rain just echo the template
|
||||
// Rain just echo the template
|
||||
|
||||
if( !$this->cache && !$return_string ){
|
||||
extract( $this->var );
|
||||
include $this->tpl['compiled_filename'];
|
||||
unset( $this->tpl );
|
||||
}
|
||||
if( !$this->cache && !$return_string ){
|
||||
extract( $this->var );
|
||||
include $this->tpl['compiled_filename'];
|
||||
unset( $this->tpl );
|
||||
}
|
||||
|
||||
|
||||
// cache or return_string are enabled
|
||||
// rain get the output buffer to save the output in the cache or to return it as string
|
||||
// rain get the output buffer to save the output in the cache or to return it as string
|
||||
|
||||
else{
|
||||
else{
|
||||
|
||||
//----------------------
|
||||
// get the output buffer
|
||||
//----------------------
|
||||
ob_start();
|
||||
extract( $this->var );
|
||||
include $this->tpl['compiled_filename'];
|
||||
$raintpl_contents = ob_get_clean();
|
||||
//----------------------
|
||||
//----------------------
|
||||
// get the output buffer
|
||||
//----------------------
|
||||
ob_start();
|
||||
extract( $this->var );
|
||||
include $this->tpl['compiled_filename'];
|
||||
$raintpl_contents = ob_get_clean();
|
||||
//----------------------
|
||||
|
||||
|
||||
// save the output in the cache
|
||||
if( $this->cache )
|
||||
file_put_contents( $this->tpl['cache_filename'], "<?php if(!class_exists('raintpl')){exit;}?>" . $raintpl_contents );
|
||||
// save the output in the cache
|
||||
if( $this->cache )
|
||||
file_put_contents( $this->tpl['cache_filename'], "<?php if(!class_exists('raintpl')){exit;}?>" . $raintpl_contents );
|
||||
|
||||
// free memory
|
||||
unset( $this->tpl );
|
||||
// free memory
|
||||
unset( $this->tpl );
|
||||
|
||||
// return or print the template
|
||||
if( $return_string ) return $raintpl_contents; else echo $raintpl_contents;
|
||||
// return or print the template
|
||||
if( $return_string ) return $raintpl_contents; else echo $raintpl_contents;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -258,15 +258,15 @@ class RainTPL{
|
||||
*/
|
||||
public function cache( $tpl_name, $expire_time = self::CACHE_EXPIRE_TIME, $cache_id = '' ){
|
||||
|
||||
// set the cache_id
|
||||
$this->cache_id = $cache_id;
|
||||
// set the cache_id
|
||||
$this->cache_id = $cache_id;
|
||||
|
||||
if( !$this->check_template( $tpl_name ) && file_exists( $this->tpl['cache_filename'] ) && ( time() - filemtime( $this->tpl['cache_filename'] ) < $expire_time ) )
|
||||
return substr( file_get_contents( $this->tpl['cache_filename'] ), 43 );
|
||||
else{
|
||||
//delete the cache of the selected template
|
||||
if (file_exists($this->tpl['cache_filename']))
|
||||
unlink($this->tpl['cache_filename'] );
|
||||
if (file_exists($this->tpl['cache_filename']))
|
||||
unlink($this->tpl['cache_filename'] );
|
||||
$this->cache = true;
|
||||
}
|
||||
}
|
||||
@@ -287,8 +287,8 @@ class RainTPL{
|
||||
self::configure( $key, $value );
|
||||
else if( property_exists( __CLASS__, $setting ) ){
|
||||
self::$$setting = $value;
|
||||
self::$config_name_sum[ $setting ] = $value; // take trace of all config
|
||||
}
|
||||
self::$config_name_sum[ $setting ] = $value; // take trace of all config
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -305,13 +305,13 @@ class RainTPL{
|
||||
|
||||
if( !isset($this->tpl['checked']) ){
|
||||
|
||||
$tpl_basename = basename( $tpl_name ); // template basename
|
||||
$tpl_basedir = strpos($tpl_name,"/") ? dirname($tpl_name) . '/' : null; // template basedirectory
|
||||
$tpl_dir = PATH . self::$tpl_dir . $tpl_basedir; // template directory
|
||||
$this->tpl['tpl_filename'] = $tpl_dir . $tpl_basename . '.' . self::$tpl_ext; // template filename
|
||||
$temp_compiled_filename = PATH . self::$cache_dir . $tpl_basename . "." . md5( $tpl_dir . serialize(self::$config_name_sum));
|
||||
$this->tpl['compiled_filename'] = $temp_compiled_filename . '.rtpl.php'; // cache filename
|
||||
$this->tpl['cache_filename'] = $temp_compiled_filename . '.s_' . $this->cache_id . '.rtpl.php'; // static cache filename
|
||||
$tpl_basename = basename( $tpl_name ); // template basename
|
||||
$tpl_basedir = strpos($tpl_name,"/") ? dirname($tpl_name) . '/' : null; // template basedirectory
|
||||
$tpl_dir = PATH . self::$tpl_dir . $tpl_basedir; // template directory
|
||||
$this->tpl['tpl_filename'] = $tpl_dir . $tpl_basename . '.' . self::$tpl_ext; // template filename
|
||||
$temp_compiled_filename = PATH . self::$cache_dir . $tpl_basename . "." . md5( $tpl_dir . serialize(self::$config_name_sum));
|
||||
$this->tpl['compiled_filename'] = $temp_compiled_filename . '.rtpl.php'; // cache filename
|
||||
$this->tpl['cache_filename'] = $temp_compiled_filename . '.s_' . $this->cache_id . '.rtpl.php'; // static cache filename
|
||||
|
||||
// if the template doesn't exsist throw an error
|
||||
if( self::$check_template_update && !file_exists( $this->tpl['tpl_filename'] ) ){
|
||||
@@ -329,6 +329,7 @@ class RainTPL{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* execute stripslaches() on the xml block. Invoqued by preg_replace_callback function below
|
||||
*
|
||||
@@ -337,9 +338,11 @@ class RainTPL{
|
||||
* @return string
|
||||
*/
|
||||
protected function xml_reSubstitution($capture) {
|
||||
return "<?php echo '<?xml ".stripslashes($capture[1])." ?>'; ?>";
|
||||
return "<?php echo '<?xml ".stripslashes($capture[1])." ?>'; ?>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compile and write the compiled template file
|
||||
*
|
||||
@@ -398,20 +401,20 @@ class RainTPL{
|
||||
protected function compileTemplate( $template_code, $tpl_basedir ){
|
||||
|
||||
//tag list
|
||||
$tag_regexp = array( 'loop' => '(\{loop(?: name){0,1}="\${0,1}[^"]*"\})',
|
||||
'loop_close' => '(\{\/loop\})',
|
||||
'if' => '(\{if(?: condition){0,1}="[^"]*"\})',
|
||||
'elseif' => '(\{elseif(?: condition){0,1}="[^"]*"\})',
|
||||
'else' => '(\{else\})',
|
||||
'if_close' => '(\{\/if\})',
|
||||
'function' => '(\{function="[^"]*"\})',
|
||||
'noparse' => '(\{noparse\})',
|
||||
'noparse_close'=> '(\{\/noparse\})',
|
||||
'ignore' => '(\{ignore\}|\{\*)',
|
||||
'ignore_close' => '(\{\/ignore\}|\*\})',
|
||||
'include' => '(\{include="[^"]*"(?: cache="[^"]*")?\})',
|
||||
'template_info'=> '(\{\$template_info\})',
|
||||
'function' => '(\{function="(\w*?)(?:.*?)"\})'
|
||||
$tag_regexp = array( 'loop' => '(\{loop(?: name){0,1}="\${0,1}[^"]*"\})',
|
||||
'loop_close' => '(\{\/loop\})',
|
||||
'if' => '(\{if(?: condition){0,1}="[^"]*"\})',
|
||||
'elseif' => '(\{elseif(?: condition){0,1}="[^"]*"\})',
|
||||
'else' => '(\{else\})',
|
||||
'if_close' => '(\{\/if\})',
|
||||
'function' => '(\{function="[^"]*"\})',
|
||||
'noparse' => '(\{noparse\})',
|
||||
'noparse_close'=> '(\{\/noparse\})',
|
||||
'ignore' => '(\{ignore\}|\{\*)',
|
||||
'ignore_close' => '(\{\/ignore\}|\*\})',
|
||||
'include' => '(\{include="[^"]*"(?: cache="[^"]*")?\})',
|
||||
'template_info'=> '(\{\$template_info\})',
|
||||
'function' => '(\{function="(\w*?)(?:.*?)"\})'
|
||||
);
|
||||
|
||||
$tag_regexp = "/" . join( "|", $tag_regexp ) . "/";
|
||||
@@ -444,35 +447,35 @@ class RainTPL{
|
||||
|
||||
//variables initialization
|
||||
$compiled_code = $open_if = $comment_is_open = $ignore_is_open = null;
|
||||
$loop_level = 0;
|
||||
$loop_level = 0;
|
||||
|
||||
//read all parsed code
|
||||
while( $html = array_shift( $parsed_code ) ){
|
||||
//read all parsed code
|
||||
while( $html = array_shift( $parsed_code ) ){
|
||||
|
||||
//close ignore tag
|
||||
//close ignore tag
|
||||
if( !$comment_is_open && ( strpos( $html, '{/ignore}' ) !== FALSE || strpos( $html, '*}' ) !== FALSE ) )
|
||||
$ignore_is_open = false;
|
||||
$ignore_is_open = false;
|
||||
|
||||
//code between tag ignore id deleted
|
||||
elseif( $ignore_is_open ){
|
||||
//ignore the code
|
||||
}
|
||||
//code between tag ignore id deleted
|
||||
elseif( $ignore_is_open ){
|
||||
//ignore the code
|
||||
}
|
||||
|
||||
//close no parse tag
|
||||
//close no parse tag
|
||||
elseif( strpos( $html, '{/noparse}' ) !== FALSE )
|
||||
$comment_is_open = false;
|
||||
$comment_is_open = false;
|
||||
|
||||
//code between tag noparse is not compiled
|
||||
elseif( $comment_is_open )
|
||||
$compiled_code .= $html;
|
||||
//code between tag noparse is not compiled
|
||||
elseif( $comment_is_open )
|
||||
$compiled_code .= $html;
|
||||
|
||||
//ignore
|
||||
//ignore
|
||||
elseif( strpos( $html, '{ignore}' ) !== FALSE || strpos( $html, '{*' ) !== FALSE )
|
||||
$ignore_is_open = true;
|
||||
$ignore_is_open = true;
|
||||
|
||||
//noparse
|
||||
elseif( strpos( $html, '{noparse}' ) !== FALSE )
|
||||
$comment_is_open = true;
|
||||
//noparse
|
||||
elseif( strpos( $html, '{noparse}' ) !== FALSE )
|
||||
$comment_is_open = true;
|
||||
|
||||
//include tag
|
||||
elseif( preg_match( '/\{include="([^"]*)"(?: cache="([^"]*)"){0,1}\}/', $html, $code ) ){
|
||||
@@ -509,19 +512,19 @@ class RainTPL{
|
||||
|
||||
}
|
||||
|
||||
//loop
|
||||
//loop
|
||||
elseif( preg_match( '/\{loop(?: name){0,1}="\${0,1}([^"]*)"\}/', $html, $code ) ){
|
||||
|
||||
//increase the loop counter
|
||||
$loop_level++;
|
||||
//increase the loop counter
|
||||
$loop_level++;
|
||||
|
||||
//replace the variable in the loop
|
||||
$var = $this->var_replace( '$' . $code[ 1 ], $tag_left_delimiter=null, $tag_right_delimiter=null, $php_left_delimiter=null, $php_right_delimiter=null, $loop_level-1 );
|
||||
|
||||
//loop variables
|
||||
$counter = "\$counter$loop_level"; // count iteration
|
||||
$key = "\$key$loop_level"; // key
|
||||
$value = "\$value$loop_level"; // value
|
||||
$counter = "\$counter$loop_level"; // count iteration
|
||||
$key = "\$key$loop_level"; // key
|
||||
$value = "\$value$loop_level"; // value
|
||||
|
||||
//loop code
|
||||
$compiled_code .= "<?php $counter=-1; if( isset($var) && is_array($var) && sizeof($var) ) foreach( $var as $key => $value ){ $counter++; ?>";
|
||||
@@ -653,6 +656,7 @@ class RainTPL{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reduce a path
|
||||
*
|
||||
@@ -672,7 +676,7 @@ class RainTPL{
|
||||
|
||||
/**
|
||||
* replace the path of image src, link href and a href
|
||||
*
|
||||
*
|
||||
* url => template_dir/url
|
||||
* url# => url
|
||||
* http://url => http://url
|
||||
@@ -728,8 +732,6 @@ class RainTPL{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* replace constants
|
||||
*
|
||||
@@ -812,28 +814,28 @@ class RainTPL{
|
||||
//if there's a function
|
||||
if( $function_var ){
|
||||
|
||||
// check if there's a function or a static method and separate, function by parameters
|
||||
// check if there's a function or a static method and separate, function by parameters
|
||||
$function_var = str_replace("::", "@double_dot@", $function_var );
|
||||
|
||||
// get the position of the first :
|
||||
if( $dot_position = strpos( $function_var, ":" ) ){
|
||||
// get the position of the first :
|
||||
if( $dot_position = strpos( $function_var, ":" ) ){
|
||||
|
||||
// get the function and the parameters
|
||||
$function = substr( $function_var, 0, $dot_position );
|
||||
$params = substr( $function_var, $dot_position+1 );
|
||||
// get the function and the parameters
|
||||
$function = substr( $function_var, 0, $dot_position );
|
||||
$params = substr( $function_var, $dot_position+1 );
|
||||
|
||||
}
|
||||
else{
|
||||
}
|
||||
else{
|
||||
|
||||
//get the function
|
||||
$function = str_replace( "@double_dot@", "::", $function_var );
|
||||
$params = null;
|
||||
//get the function
|
||||
$function = str_replace( "@double_dot@", "::", $function_var );
|
||||
$params = null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// replace back the @double_dot@ with ::
|
||||
$function = str_replace( "@double_dot@", "::", $function );
|
||||
$params = str_replace( "@double_dot@", "::", $params );
|
||||
// replace back the @double_dot@ with ::
|
||||
$function = str_replace( "@double_dot@", "::", $function );
|
||||
$params = str_replace( "@double_dot@", "::", $params );
|
||||
|
||||
|
||||
}
|
||||
@@ -880,105 +882,105 @@ class RainTPL{
|
||||
//all variables
|
||||
if( preg_match_all( '/' . $tag_left_delimiter . '\$(\w+(?:\.\${0,1}[A-Za-z0-9_]+)*(?:(?:\[\${0,1}[A-Za-z0-9_]+\])|(?:\-\>\${0,1}[A-Za-z0-9_]+))*)(.*?)' . $tag_right_delimiter . '/', $html, $matches ) ){
|
||||
|
||||
for( $parsed=array(), $i=0, $n=count($matches[0]); $i<$n; $i++ )
|
||||
$parsed[$matches[0][$i]] = array('var'=>$matches[1][$i],'extra_var'=>$matches[2][$i]);
|
||||
for( $parsed=array(), $i=0, $n=count($matches[0]); $i<$n; $i++ )
|
||||
$parsed[$matches[0][$i]] = array('var'=>$matches[1][$i],'extra_var'=>$matches[2][$i]);
|
||||
|
||||
foreach( $parsed as $tag => $array ){
|
||||
foreach( $parsed as $tag => $array ){
|
||||
|
||||
//variable name ex: news.title
|
||||
$var = $array['var'];
|
||||
//variable name ex: news.title
|
||||
$var = $array['var'];
|
||||
|
||||
//function and parameters associate to the variable ex: substr:0,100
|
||||
$extra_var = $array['extra_var'];
|
||||
//function and parameters associate to the variable ex: substr:0,100
|
||||
$extra_var = $array['extra_var'];
|
||||
|
||||
// check if there's any function disabled by black_list
|
||||
$this->function_check( $tag );
|
||||
// check if there's any function disabled by black_list
|
||||
$this->function_check( $tag );
|
||||
|
||||
$extra_var = $this->var_replace( $extra_var, null, null, null, null, $loop_level );
|
||||
$extra_var = $this->var_replace( $extra_var, null, null, null, null, $loop_level );
|
||||
|
||||
// check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value
|
||||
$is_init_variable = preg_match( "/^[a-z_A-Z\.\[\](\-\>)]*=[^=]*$/", $extra_var );
|
||||
// check if there's an operator = in the variable tags, if there's this is an initialization so it will not output any value
|
||||
$is_init_variable = preg_match( "/^[a-z_A-Z\.\[\](\-\>)]*=[^=]*$/", $extra_var );
|
||||
|
||||
//function associate to variable
|
||||
$function_var = ( $extra_var and $extra_var[0] == '|') ? substr( $extra_var, 1 ) : null;
|
||||
//function associate to variable
|
||||
$function_var = ( $extra_var and $extra_var[0] == '|') ? substr( $extra_var, 1 ) : null;
|
||||
|
||||
//variable path split array (ex. $news.title o $news[title]) or object (ex. $news->title)
|
||||
$temp = preg_split( "/\.|\[|\-\>/", $var );
|
||||
//variable path split array (ex. $news.title o $news[title]) or object (ex. $news->title)
|
||||
$temp = preg_split( "/\.|\[|\-\>/", $var );
|
||||
|
||||
//variable name
|
||||
$var_name = $temp[ 0 ];
|
||||
//variable name
|
||||
$var_name = $temp[ 0 ];
|
||||
|
||||
//variable path
|
||||
$variable_path = substr( $var, strlen( $var_name ) );
|
||||
//variable path
|
||||
$variable_path = substr( $var, strlen( $var_name ) );
|
||||
|
||||
//parentesis transform [ e ] in [" e in "]
|
||||
$variable_path = str_replace( '[', '["', $variable_path );
|
||||
$variable_path = str_replace( ']', '"]', $variable_path );
|
||||
//parentesis transform [ e ] in [" e in "]
|
||||
$variable_path = str_replace( '[', '["', $variable_path );
|
||||
$variable_path = str_replace( ']', '"]', $variable_path );
|
||||
|
||||
//transform .$variable in ["$variable"] and .variable in ["variable"]
|
||||
$variable_path = preg_replace('/\.(\${0,1}\w+)/', '["\\1"]', $variable_path );
|
||||
//transform .$variable in ["$variable"] and .variable in ["variable"]
|
||||
$variable_path = preg_replace('/\.(\${0,1}\w+)/', '["\\1"]', $variable_path );
|
||||
|
||||
// if is an assignment also assign the variable to $this->var['value']
|
||||
if( $is_init_variable )
|
||||
$extra_var = "=\$this->var['{$var_name}']{$variable_path}" . $extra_var;
|
||||
// if is an assignment also assign the variable to $this->var['value']
|
||||
if( $is_init_variable )
|
||||
$extra_var = "=\$this->var['{$var_name}']{$variable_path}" . $extra_var;
|
||||
|
||||
|
||||
|
||||
//if there's a function
|
||||
if( $function_var ){
|
||||
//if there's a function
|
||||
if( $function_var ){
|
||||
|
||||
// check if there's a function or a static method and separate, function by parameters
|
||||
$function_var = str_replace("::", "@double_dot@", $function_var );
|
||||
// check if there's a function or a static method and separate, function by parameters
|
||||
$function_var = str_replace("::", "@double_dot@", $function_var );
|
||||
|
||||
|
||||
// get the position of the first :
|
||||
if( $dot_position = strpos( $function_var, ":" ) ){
|
||||
// get the position of the first :
|
||||
if( $dot_position = strpos( $function_var, ":" ) ){
|
||||
|
||||
// get the function and the parameters
|
||||
$function = substr( $function_var, 0, $dot_position );
|
||||
$params = substr( $function_var, $dot_position+1 );
|
||||
// get the function and the parameters
|
||||
$function = substr( $function_var, 0, $dot_position );
|
||||
$params = substr( $function_var, $dot_position+1 );
|
||||
|
||||
}
|
||||
else{
|
||||
}
|
||||
else{
|
||||
|
||||
//get the function
|
||||
$function = str_replace( "@double_dot@", "::", $function_var );
|
||||
$params = null;
|
||||
//get the function
|
||||
$function = str_replace( "@double_dot@", "::", $function_var );
|
||||
$params = null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// replace back the @double_dot@ with ::
|
||||
$function = str_replace( "@double_dot@", "::", $function );
|
||||
$params = str_replace( "@double_dot@", "::", $params );
|
||||
}
|
||||
else
|
||||
$function = $params = null;
|
||||
// replace back the @double_dot@ with ::
|
||||
$function = str_replace( "@double_dot@", "::", $function );
|
||||
$params = str_replace( "@double_dot@", "::", $params );
|
||||
}
|
||||
else
|
||||
$function = $params = null;
|
||||
|
||||
//if it is inside a loop
|
||||
if( $loop_level ){
|
||||
//verify the variable name
|
||||
if( $var_name == 'key' )
|
||||
$php_var = '$key' . $loop_level;
|
||||
elseif( $var_name == 'value' )
|
||||
$php_var = '$value' . $loop_level . $variable_path;
|
||||
elseif( $var_name == 'counter' )
|
||||
$php_var = '$counter' . $loop_level;
|
||||
else
|
||||
$php_var = '$' . $var_name . $variable_path;
|
||||
}else
|
||||
$php_var = '$' . $var_name . $variable_path;
|
||||
//if it is inside a loop
|
||||
if( $loop_level ){
|
||||
//verify the variable name
|
||||
if( $var_name == 'key' )
|
||||
$php_var = '$key' . $loop_level;
|
||||
elseif( $var_name == 'value' )
|
||||
$php_var = '$value' . $loop_level . $variable_path;
|
||||
elseif( $var_name == 'counter' )
|
||||
$php_var = '$counter' . $loop_level;
|
||||
else
|
||||
$php_var = '$' . $var_name . $variable_path;
|
||||
}else
|
||||
$php_var = '$' . $var_name . $variable_path;
|
||||
|
||||
// compile the variable for php
|
||||
if( isset( $function ) )
|
||||
$php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . ( $params ? "( $function( $php_var, $params ) )" : "$function( $php_var )" ) . $php_right_delimiter;
|
||||
else
|
||||
$php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . $php_var . $extra_var . $php_right_delimiter;
|
||||
// compile the variable for php
|
||||
if( isset( $function ) )
|
||||
$php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . ( $params ? "( $function( $php_var, $params ) )" : "$function( $php_var )" ) . $php_right_delimiter;
|
||||
else
|
||||
$php_var = $php_left_delimiter . ( !$is_init_variable && $echo ? 'echo ' : null ) . $php_var . $extra_var . $php_right_delimiter;
|
||||
|
||||
$html = str_replace( $tag, $php_var, $html );
|
||||
$html = str_replace( $tag, $php_var, $html );
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
@@ -1015,6 +1017,8 @@ class RainTPL{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Prints debug info about exception or passes it further if debug is disabled.
|
||||
*
|
||||
@@ -1053,6 +1057,7 @@ class RainTPL{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Basic Rain tpl exception.
|
||||
*/
|
||||
@@ -1085,6 +1090,8 @@ class RainTpl_Exception extends Exception{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown when template file does not exists.
|
||||
*/
|
||||
@@ -1155,4 +1162,18 @@ class RainTpl_SyntaxException extends RainTpl_Exception{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* shorthand translate function for use in templates
|
||||
*
|
||||
* alias for i18n::translate()
|
||||
*
|
||||
* @access public
|
||||
* @param string $messageId
|
||||
* @param mixed $args one or multiple parameters injected into placeholders
|
||||
* @return string
|
||||
*/
|
||||
function t() {
|
||||
return call_user_func_array(array('i18n', 'translate'), func_get_args());
|
||||
}
|
||||
|
||||
// -- end
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
spl_autoload_register('auto::loader');
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -33,7 +33,36 @@ class filter
|
||||
}
|
||||
|
||||
/**
|
||||
* format a given number of bytes
|
||||
* format a given time string into a human readable label (localized)
|
||||
*
|
||||
* accepts times in the format "[integer][time unit]"
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $time
|
||||
* @throws Exception
|
||||
* @return string
|
||||
*/
|
||||
public static function time_humanreadable($time)
|
||||
{
|
||||
if (preg_match('/^(\d+) *(\w+)$/', $time, $matches) !== 1) {
|
||||
throw new Exception("Error parsing time format '$time'", 30);
|
||||
}
|
||||
switch ($matches[2]) {
|
||||
case 'sec':
|
||||
$unit = 'second';
|
||||
break;
|
||||
case 'min':
|
||||
$unit = 'minute';
|
||||
break;
|
||||
default:
|
||||
$unit = rtrim($matches[2], 's');
|
||||
}
|
||||
return i18n::_(array('%d ' . $unit, '%d ' . $unit . 's'), (int) $matches[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* format a given number of bytes in IEC 80000-13:2008 notation (localized)
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
@@ -42,13 +71,13 @@ class filter
|
||||
*/
|
||||
public static function size_humanreadable($size)
|
||||
{
|
||||
$iec = array('B', 'kiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB');
|
||||
$iec = array('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB');
|
||||
$i = 0;
|
||||
while ( ( $size / 1024 ) >= 1 ) {
|
||||
$size = $size / 1024;
|
||||
$i++;
|
||||
}
|
||||
return number_format($size, ($i ? 2 : 0), '.', ' ') . ' ' . $iec[$i];
|
||||
return number_format($size, ($i ? 2 : 0), '.', ' ') . ' ' . i18n::_($iec[$i]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
369
lib/i18n.php
Normal file
369
lib/i18n.php
Normal file
@@ -0,0 +1,369 @@
|
||||
<?php
|
||||
/**
|
||||
* ZeroBin
|
||||
*
|
||||
* a zero-knowledge paste bin
|
||||
*
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
* i18n
|
||||
*
|
||||
* provides internationalization tools like translation, browser language detection, etc.
|
||||
*/
|
||||
class i18n
|
||||
{
|
||||
/**
|
||||
* language
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @var string
|
||||
*/
|
||||
protected static $_language = 'en';
|
||||
|
||||
/**
|
||||
* language labels
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @var array
|
||||
*/
|
||||
protected static $_languageLabels = array();
|
||||
|
||||
/**
|
||||
* available languages
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @var array
|
||||
*/
|
||||
protected static $_availableLanguages = array();
|
||||
|
||||
/**
|
||||
* path to language files
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @var string
|
||||
*/
|
||||
protected static $_path = '';
|
||||
|
||||
/**
|
||||
* translation cache
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @var array
|
||||
*/
|
||||
protected static $_translations = array();
|
||||
|
||||
/**
|
||||
* translate a string, alias for translate()
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $messageId
|
||||
* @param mixed $args one or multiple parameters injected into placeholders
|
||||
* @return string
|
||||
*/
|
||||
public static function _($messageId)
|
||||
{
|
||||
return call_user_func_array(array('i18n', 'translate'), func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* translate a string
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param string $messageId
|
||||
* @param mixed $args one or multiple parameters injected into placeholders
|
||||
* @return string
|
||||
*/
|
||||
public static function translate($messageId)
|
||||
{
|
||||
if (empty($messageId)) return $messageId;
|
||||
if (count(self::$_translations) === 0) self::loadTranslations();
|
||||
$messages = $messageId;
|
||||
if (is_array($messageId))
|
||||
{
|
||||
$messageId = count($messageId) > 1 ? $messageId[1] : $messageId[0];
|
||||
}
|
||||
if (!array_key_exists($messageId, self::$_translations))
|
||||
{
|
||||
self::$_translations[$messageId] = $messages;
|
||||
}
|
||||
$args = func_get_args();
|
||||
if (is_array(self::$_translations[$messageId]))
|
||||
{
|
||||
$number = (int) $args[1];
|
||||
$key = self::_getPluralForm($number);
|
||||
$max = count(self::$_translations[$messageId]) - 1;
|
||||
if ($key > $max) $key = $max;
|
||||
|
||||
$args[0] = self::$_translations[$messageId][$key];
|
||||
$args[1] = $number;
|
||||
}
|
||||
else
|
||||
{
|
||||
$args[0] = self::$_translations[$messageId];
|
||||
}
|
||||
return call_user_func_array('sprintf', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* loads translations
|
||||
*
|
||||
* From: http://stackoverflow.com/questions/3770513/detect-browser-language-in-php#3771447
|
||||
*
|
||||
* @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'];
|
||||
}
|
||||
// find a translation file matching the browsers language preferences
|
||||
else
|
||||
{
|
||||
$match = self::_getMatchingLanguage(
|
||||
self::getBrowserLanguages(), $availableLanguages
|
||||
);
|
||||
}
|
||||
|
||||
// load translations
|
||||
self::$_language = $match;
|
||||
self::$_translations = ($match == 'en') ? array() : json_decode(
|
||||
file_get_contents(self::_getPath($match . '.json')),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* get list of available translations based on files found
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @return array
|
||||
*/
|
||||
public static function getAvailableLanguages()
|
||||
{
|
||||
if (count(self::$_availableLanguages) == 0)
|
||||
{
|
||||
$i18n = dir(self::_getPath());
|
||||
while (false !== ($file = $i18n->read()))
|
||||
{
|
||||
if (preg_match('/^([a-z]{2}).json$/', $file, $match) === 1)
|
||||
{
|
||||
self::$_availableLanguages[] = $match[1];
|
||||
}
|
||||
}
|
||||
self::$_availableLanguages[] = 'en';
|
||||
}
|
||||
return self::$_availableLanguages;
|
||||
}
|
||||
|
||||
/**
|
||||
* detect the clients supported languages and return them ordered by preference
|
||||
*
|
||||
* From: http://stackoverflow.com/questions/3770513/detect-browser-language-in-php#3771447
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @return array
|
||||
*/
|
||||
public static function getBrowserLanguages()
|
||||
{
|
||||
$languages = array();
|
||||
if (array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER))
|
||||
{
|
||||
$languageRanges = explode(',', trim($_SERVER['HTTP_ACCEPT_LANGUAGE']));
|
||||
foreach ($languageRanges as $languageRange) {
|
||||
if (preg_match(
|
||||
'/(\*|[a-zA-Z0-9]{1,8}(?:-[a-zA-Z0-9]{1,8})*)(?:\s*;\s*q\s*=\s*(0(?:\.\d{0,3})|1(?:\.0{0,3})))?/',
|
||||
trim($languageRange), $match
|
||||
))
|
||||
{
|
||||
if (!isset($match[2]))
|
||||
{
|
||||
$match[2] = '1.0';
|
||||
}
|
||||
else
|
||||
{
|
||||
$match[2] = (string) floatval($match[2]);
|
||||
}
|
||||
if (!isset($languages[$match[2]]))
|
||||
{
|
||||
$languages[$match[2]] = array();
|
||||
}
|
||||
$languages[$match[2]][] = strtolower($match[1]);
|
||||
}
|
||||
}
|
||||
krsort($languages);
|
||||
}
|
||||
return $languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* get currently loaded language
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
public static function getLanguage()
|
||||
{
|
||||
return self::$_language;
|
||||
}
|
||||
|
||||
/**
|
||||
* get list of language labels
|
||||
*
|
||||
* Only for given language codes, otherwise all labels.
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @param array $languages
|
||||
* @return array
|
||||
*/
|
||||
public static function getLanguageLabels($languages = array())
|
||||
{
|
||||
$file = self::_getPath('languages.json');
|
||||
if (count(self::$_languageLabels) == 0 && is_readable($file))
|
||||
{
|
||||
self::$_languageLabels = json_decode(file_get_contents($file), true);
|
||||
}
|
||||
if (count($languages) == 0) return self::$_languageLabels;
|
||||
return array_intersect_key(self::$_languageLabels, array_flip($languages));
|
||||
}
|
||||
|
||||
/**
|
||||
* get language file path
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @param string $file
|
||||
* @return string
|
||||
*/
|
||||
protected static function _getPath($file = '')
|
||||
{
|
||||
if (strlen(self::$_path) == 0)
|
||||
{
|
||||
self::$_path = PUBLIC_PATH . DIRECTORY_SEPARATOR . 'i18n';
|
||||
}
|
||||
return self::$_path . (strlen($file) ? DIRECTORY_SEPARATOR . $file : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* determines the plural form to use based on current language and given number
|
||||
*
|
||||
* From: http://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @param int $n
|
||||
* @return int
|
||||
*/
|
||||
protected static function _getPluralForm($n)
|
||||
{
|
||||
switch (self::$_language) {
|
||||
case 'fr':
|
||||
return ($n > 1 ? 1 : 0);
|
||||
case 'pl':
|
||||
return ($n == 1 ? 0 : $n%10 >= 2 && $n %10 <=4 && ($n%100 < 10 || $n%100 >= 20) ? 1 : 2);
|
||||
// en, de
|
||||
default:
|
||||
return ($n != 1 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* compares two language preference arrays and returns the preferred match
|
||||
*
|
||||
* From: http://stackoverflow.com/questions/3770513/detect-browser-language-in-php#3771447
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @param array $acceptedLanguages
|
||||
* @param array $availableLanguages
|
||||
* @return string
|
||||
*/
|
||||
protected static function _getMatchingLanguage($acceptedLanguages, $availableLanguages) {
|
||||
$matches = array();
|
||||
$any = false;
|
||||
foreach ($acceptedLanguages as $acceptedQuality => $acceptedValues) {
|
||||
$acceptedQuality = floatval($acceptedQuality);
|
||||
if ($acceptedQuality === 0.0) continue;
|
||||
foreach ($availableLanguages as $availableValue)
|
||||
{
|
||||
$availableQuality = 1.0;
|
||||
foreach ($acceptedValues as $acceptedValue)
|
||||
{
|
||||
if ($acceptedValue === '*')
|
||||
{
|
||||
$any = true;
|
||||
}
|
||||
$matchingGrade = self::_matchLanguage($acceptedValue, $availableValue);
|
||||
if ($matchingGrade > 0)
|
||||
{
|
||||
$q = (string) ($acceptedQuality * $availableQuality * $matchingGrade);
|
||||
if (!isset($matches[$q]))
|
||||
{
|
||||
$matches[$q] = array();
|
||||
}
|
||||
if (!in_array($availableValue, $matches[$q]))
|
||||
{
|
||||
$matches[$q][] = $availableValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count($matches) === 0 && $any)
|
||||
{
|
||||
if (count($availableLanguages) > 0)
|
||||
{
|
||||
$matches['1.0'] = $availableLanguages;
|
||||
}
|
||||
}
|
||||
if (count($matches) === 0)
|
||||
{
|
||||
return 'en';
|
||||
}
|
||||
krsort($matches);
|
||||
$topmatches = current($matches);
|
||||
return current($topmatches);
|
||||
}
|
||||
|
||||
/**
|
||||
* compare two language IDs and return the degree they match
|
||||
*
|
||||
* From: http://stackoverflow.com/questions/3770513/detect-browser-language-in-php#3771447
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return float
|
||||
*/
|
||||
protected static function _matchLanguage($a, $b) {
|
||||
$a = explode('-', $a);
|
||||
$b = explode('-', $b);
|
||||
for ($i=0, $n=min(count($a), count($b)); $i<$n; $i++)
|
||||
{
|
||||
if ($a[$i] !== $b[$i]) break;
|
||||
}
|
||||
return $i === 0 ? 0 : (float) $i / count($a);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.0.4 beta ZeroBin 0.20
|
||||
* @version 0.0.4 beta ZeroBin 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
228
lib/zerobin.php
228
lib/zerobin.php
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -22,7 +22,7 @@ class zerobin
|
||||
*
|
||||
* @const string
|
||||
*/
|
||||
const VERSION = '0.20';
|
||||
const VERSION = '0.21';
|
||||
|
||||
/**
|
||||
* show the same error message if the paste expired or does not exist
|
||||
@@ -49,6 +49,14 @@ class zerobin
|
||||
*/
|
||||
private $_data = '';
|
||||
|
||||
/**
|
||||
* formatter
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_formatter = 'plaintext';
|
||||
|
||||
/**
|
||||
* error message
|
||||
*
|
||||
@@ -93,7 +101,7 @@ class zerobin
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.2.6') < 0)
|
||||
{
|
||||
throw new Exception('ZeroBin requires php 5.2.6 or above to work. Sorry.', 1);
|
||||
throw new Exception(i18n::_('ZeroBin requires php 5.2.6 or above to work. Sorry.'), 1);
|
||||
}
|
||||
|
||||
// in case stupid admin has left magic_quotes enabled in php.ini
|
||||
@@ -108,9 +116,12 @@ class zerobin
|
||||
$this->_init();
|
||||
|
||||
// create new paste or comment
|
||||
if (!empty($_POST['data']))
|
||||
if (
|
||||
(array_key_exists('data', $_POST) && !empty($_POST['data'])) ||
|
||||
(array_key_exists('attachment', $_POST) && !empty($_POST['attachment']))
|
||||
)
|
||||
{
|
||||
$this->_create($_POST['data']);
|
||||
$this->_create();
|
||||
}
|
||||
// delete an existing paste
|
||||
elseif (!empty($_GET['deletetoken']) && !empty($_GET['pasteid']))
|
||||
@@ -156,7 +167,7 @@ class zerobin
|
||||
$this->_conf = parse_ini_file(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', true);
|
||||
foreach (array('main', 'model') as $section) {
|
||||
if (!array_key_exists($section, $this->_conf)) {
|
||||
throw new Exception("ZeroBin requires configuration section [$section] to be present in configuration file.", 2);
|
||||
throw new Exception(i18n::_('ZeroBin requires configuration section [%s] to be present in configuration file.', $section), 2);
|
||||
}
|
||||
}
|
||||
$this->_model = $this->_conf['model']['class'];
|
||||
@@ -183,71 +194,97 @@ class zerobin
|
||||
/**
|
||||
* Store new paste or comment
|
||||
*
|
||||
* POST contains:
|
||||
* data (mandatory) = json encoded SJCL encrypted text (containing keys: iv,salt,ct)
|
||||
* POST contains one or both:
|
||||
* data = json encoded SJCL encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
* attachment = json encoded SJCL encrypted text (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
*
|
||||
* All optional data will go to meta information:
|
||||
* expire (optional) = expiration delay (never,5min,10min,1hour,1day,1week,1month,1year,burn) (default:never)
|
||||
* formatter (optional) = format to display the paste as (plaintext,syntaxhighlighting,markdown) (default:syntaxhighlighting)
|
||||
* burnafterreading (optional) = if this paste may only viewed once ? (0/1) (default:0)
|
||||
* opendiscusssion (optional) = is the discussion allowed on this paste ? (0/1) (default:0)
|
||||
* nickname (optional) = in discussion, encoded SJCL encrypted text nickname of author of comment (containing keys: iv,salt,ct)
|
||||
* nickname (optional) = in discussion, encoded SJCL encrypted text nickname of author of comment (containing keys: iv,v,iter,ks,ts,mode,adata,cipher,salt,ct)
|
||||
* parentid (optional) = in discussion, which comment this comment replies to.
|
||||
* pasteid (optional) = in discussion, which paste this comment belongs to.
|
||||
*
|
||||
* @access private
|
||||
* @param string $data
|
||||
* @return string
|
||||
*/
|
||||
private function _create($data)
|
||||
private function _create()
|
||||
{
|
||||
$error = false;
|
||||
|
||||
$has_attachment = array_key_exists('attachment', $_POST);
|
||||
$has_attachmentname = $has_attachment && array_key_exists('attachmentname', $_POST) && !empty($_POST['attachmentname']);
|
||||
$data = array_key_exists('data', $_POST) ? $_POST['data'] : '';
|
||||
$attachment = $has_attachment ? $_POST['attachment'] : '';
|
||||
$attachmentname = $has_attachmentname ? $_POST['attachmentname'] : '';
|
||||
|
||||
// Make sure last paste from the IP address was more than X seconds ago.
|
||||
trafficlimiter::setLimit($this->_conf['traffic']['limit']);
|
||||
trafficlimiter::setPath($this->_conf['traffic']['dir']);
|
||||
if (!trafficlimiter::canPass($_SERVER['REMOTE_ADDR']))
|
||||
$ipKey = 'REMOTE_ADDR';
|
||||
if (array_key_exists('header', $this->_conf['traffic']))
|
||||
{
|
||||
$this->_return_message(
|
||||
1,
|
||||
'Please wait ' .
|
||||
$this->_conf['traffic']['limit'] .
|
||||
' seconds between each post.'
|
||||
);
|
||||
return;
|
||||
$header = 'HTTP_' . $this->_conf['traffic']['header'];
|
||||
if (array_key_exists($header, $_SERVER) && !empty($_SERVER[$header]))
|
||||
{
|
||||
$ipKey = $header;
|
||||
}
|
||||
}
|
||||
if (!trafficlimiter::canPass($_SERVER[$ipKey])) return $this->_return_message(
|
||||
1,
|
||||
i18n::_(
|
||||
'Please wait %d seconds between each post.',
|
||||
$this->_conf['traffic']['limit']
|
||||
)
|
||||
);
|
||||
|
||||
// Make sure content is not too big.
|
||||
$sizelimit = (int) $this->_getMainConfig('sizelimit', 2097152);
|
||||
if (strlen($data) > $sizelimit)
|
||||
{
|
||||
$this->_return_message(
|
||||
1,
|
||||
'Paste is limited to ' .
|
||||
filter::size_humanreadable($sizelimit) .
|
||||
' of encrypted data.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
strlen($data) + strlen($attachment) + strlen($attachmentname) > $sizelimit
|
||||
) return $this->_return_message(
|
||||
1,
|
||||
i18n::_(
|
||||
'Paste is limited to %s of encrypted data.',
|
||||
filter::size_humanreadable($sizelimit)
|
||||
)
|
||||
);
|
||||
|
||||
// Make sure format is correct.
|
||||
if (!sjcl::isValid($data)) return $this->_return_message(1, 'Invalid data.');
|
||||
|
||||
// Make sure attachments are enabled and format is correct.
|
||||
if($has_attachment)
|
||||
{
|
||||
if (
|
||||
!$this->_getMainConfig('fileupload', false) ||
|
||||
!sjcl::isValid($attachment) ||
|
||||
!($has_attachmentname && sjcl::isValid($attachmentname))
|
||||
) return $this->_return_message(1, 'Invalid attachment.');
|
||||
}
|
||||
|
||||
// Read additional meta-information.
|
||||
$meta=array();
|
||||
$meta = array();
|
||||
|
||||
// Read expiration date
|
||||
if (!empty($_POST['expire']))
|
||||
if (array_key_exists('expire', $_POST) && !empty($_POST['expire']))
|
||||
{
|
||||
$selected_expire = (string) $_POST['expire'];
|
||||
if (array_key_exists($selected_expire, $this->_conf['expire_options'])) {
|
||||
if (array_key_exists($selected_expire, $this->_conf['expire_options']))
|
||||
{
|
||||
$expire = $this->_conf['expire_options'][$selected_expire];
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$expire = $this->_conf['expire_options'][$this->_conf['expire']['default']];
|
||||
}
|
||||
if ($expire > 0) $meta['expire_date'] = time() + $expire;
|
||||
}
|
||||
|
||||
// Destroy the paste when it is read.
|
||||
if (!empty($_POST['burnafterreading']))
|
||||
if (array_key_exists('burnafterreading', $_POST) && !empty($_POST['burnafterreading']))
|
||||
{
|
||||
$burnafterreading = $_POST['burnafterreading'];
|
||||
if ($burnafterreading !== '0')
|
||||
@@ -258,7 +295,11 @@ class zerobin
|
||||
}
|
||||
|
||||
// Read open discussion flag.
|
||||
if ($this->_conf['main']['discussion'] && !empty($_POST['opendiscussion']))
|
||||
if (
|
||||
$this->_getMainConfig('discussion', true) &&
|
||||
array_key_exists('opendiscussion', $_POST) &&
|
||||
!empty($_POST['opendiscussion'])
|
||||
)
|
||||
{
|
||||
$opendiscussion = $_POST['opendiscussion'];
|
||||
if ($opendiscussion !== '0')
|
||||
@@ -268,6 +309,17 @@ class zerobin
|
||||
}
|
||||
}
|
||||
|
||||
// Read formatter flag.
|
||||
if (array_key_exists('formatter', $_POST) && !empty($_POST['formatter']))
|
||||
{
|
||||
$formatter = $_POST['formatter'];
|
||||
if (!array_key_exists($formatter, $this->_conf['formatter_options']))
|
||||
{
|
||||
$formatter = $this->_getMainConfig('defaultformatter', 'plaintext');
|
||||
}
|
||||
$meta['formatter'] = $formatter;
|
||||
}
|
||||
|
||||
// You can't have an open discussion on a "Burn after reading" paste:
|
||||
if (isset($meta['burnafterreading'])) unset($meta['opendiscussion']);
|
||||
|
||||
@@ -296,11 +348,7 @@ class zerobin
|
||||
}
|
||||
}
|
||||
|
||||
if ($error)
|
||||
{
|
||||
$this->_return_message(1, 'Invalid data.');
|
||||
return;
|
||||
}
|
||||
if ($error) return $this->_return_message(1, 'Invalid data.');
|
||||
|
||||
// Add post date to meta.
|
||||
$meta['postdate'] = time();
|
||||
@@ -325,11 +373,7 @@ class zerobin
|
||||
if (
|
||||
!filter::is_valid_paste_id($pasteid) ||
|
||||
!filter::is_valid_paste_id($parentid)
|
||||
)
|
||||
{
|
||||
$this->_return_message(1, 'Invalid data.');
|
||||
return;
|
||||
}
|
||||
) return $this->_return_message(1, 'Invalid data.');
|
||||
|
||||
// Comments do not expire (it's the paste that expires)
|
||||
unset($storage['expire_date']);
|
||||
@@ -338,43 +382,26 @@ class zerobin
|
||||
// Make sure paste exists.
|
||||
if (
|
||||
!$this->_model()->exists($pasteid)
|
||||
)
|
||||
{
|
||||
$this->_return_message(1, 'Invalid data.');
|
||||
return;
|
||||
}
|
||||
) return $this->_return_message(1, 'Invalid data.');
|
||||
|
||||
// Make sure the discussion is opened in this paste.
|
||||
$paste = $this->_model()->read($pasteid);
|
||||
if (
|
||||
!$paste->meta->opendiscussion
|
||||
)
|
||||
{
|
||||
$this->_return_message(1, 'Invalid data.');
|
||||
return;
|
||||
}
|
||||
) return $this->_return_message(1, 'Invalid data.');
|
||||
|
||||
// Check for improbable collision.
|
||||
if (
|
||||
$this->_model()->existsComment($pasteid, $parentid, $dataid)
|
||||
)
|
||||
{
|
||||
$this->_return_message(1, 'You are unlucky. Try again.');
|
||||
return;
|
||||
}
|
||||
) return $this->_return_message(1, 'You are unlucky. Try again.');
|
||||
|
||||
// New comment
|
||||
if (
|
||||
$this->_model()->createComment($pasteid, $parentid, $dataid, $storage) === false
|
||||
)
|
||||
{
|
||||
$this->_return_message(1, 'Error saving comment. Sorry.');
|
||||
return;
|
||||
}
|
||||
) return $this->_return_message(1, 'Error saving comment. Sorry.');
|
||||
|
||||
// 0 = no error
|
||||
$this->_return_message(0, $dataid);
|
||||
return;
|
||||
return $this->_return_message(0, $dataid);
|
||||
}
|
||||
// The user posts a standard paste.
|
||||
else
|
||||
@@ -382,19 +409,16 @@ class zerobin
|
||||
// Check for improbable collision.
|
||||
if (
|
||||
$this->_model()->exists($dataid)
|
||||
)
|
||||
{
|
||||
$this->_return_message(1, 'You are unlucky. Try again.');
|
||||
return;
|
||||
}
|
||||
) return $this->_return_message(1, 'You are unlucky. Try again.');
|
||||
|
||||
// Add attachment and its name, if one was sent
|
||||
if ($has_attachment) $storage['attachment'] = $attachment;
|
||||
if ($has_attachmentname) $storage['attachmentname'] = $attachmentname;
|
||||
|
||||
// New paste
|
||||
if (
|
||||
$this->_model()->create($dataid, $storage) === false
|
||||
) {
|
||||
$this->_return_message(1, 'Error saving paste. Sorry.');
|
||||
return;
|
||||
}
|
||||
) return $this->_return_message(1, 'Error saving paste. Sorry.');
|
||||
|
||||
// Generate the "delete" token.
|
||||
// The token is the hmac of the pasteid signed with the server salt.
|
||||
@@ -402,8 +426,7 @@ class zerobin
|
||||
$deletetoken = hash_hmac('sha1', $dataid, serversalt::get());
|
||||
|
||||
// 0 = no error
|
||||
$this->_return_message(0, $dataid, array('deletetoken' => $deletetoken));
|
||||
return;
|
||||
return $this->_return_message(0, $dataid, array('deletetoken' => $deletetoken));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,6 +559,21 @@ class zerobin
|
||||
$this->_model()->readComments($dataid)
|
||||
);
|
||||
}
|
||||
|
||||
// set formatter for for the view.
|
||||
if (!property_exists($paste->meta, 'formatter'))
|
||||
{
|
||||
// support < 0.21 syntax highlighting
|
||||
if (property_exists($paste->meta, 'syntaxcoloring') && $paste->meta->syntaxcoloring === true)
|
||||
{
|
||||
$paste->meta->formatter = 'syntaxhighlighting';
|
||||
}
|
||||
else
|
||||
{
|
||||
$paste->meta->formatter = $this->_getMainConfig('defaultformatter', 'plaintext');
|
||||
}
|
||||
}
|
||||
|
||||
$this->_data = json_encode($messages);
|
||||
}
|
||||
}
|
||||
@@ -574,27 +612,43 @@ class zerobin
|
||||
|
||||
// label all the expiration options
|
||||
$expire = array();
|
||||
foreach ($this->_conf['expire_options'] as $key => $value) {
|
||||
$expire[$key] = array_key_exists($key, $this->_conf['expire_labels']) ?
|
||||
$this->_conf['expire_labels'][$key] :
|
||||
$key;
|
||||
foreach ($this->_conf['expire_options'] as $time => $seconds)
|
||||
{
|
||||
$expire[$time] = ($seconds == 0) ? i18n::_(ucfirst($time)): filter::time_humanreadable($time);
|
||||
}
|
||||
|
||||
// translate all the formatter options
|
||||
$formatters = array_map(array('i18n', 'translate'), $this->_conf['formatter_options']);
|
||||
|
||||
// set language cookie if that functionality was enabled
|
||||
$languageselection = '';
|
||||
if ($this->_getMainConfig('languageselection', false))
|
||||
{
|
||||
$languageselection = i18n::getLanguage();
|
||||
setcookie('lang', $languageselection);
|
||||
}
|
||||
|
||||
$page = new RainTPL;
|
||||
$page::$path_replace = false;
|
||||
// we escape it here because ENT_NOQUOTES can't be used in RainTPL templates
|
||||
$page->assign('CIPHERDATA', htmlspecialchars($this->_data, ENT_NOQUOTES));
|
||||
$page->assign('ERROR', $this->_error);
|
||||
$page->assign('STATUS', $this->_status);
|
||||
$page->assign('ERROR', i18n::_($this->_error));
|
||||
$page->assign('STATUS', i18n::_($this->_status));
|
||||
$page->assign('VERSION', self::VERSION);
|
||||
$page->assign('DISCUSSION', $this->_getMainConfig('discussion', true));
|
||||
$page->assign('OPENDISCUSSION', $this->_getMainConfig('opendiscussion', true));
|
||||
$page->assign('SYNTAXHIGHLIGHTING', $this->_getMainConfig('syntaxhighlighting', true));
|
||||
$page->assign('MARKDOWN', array_key_exists('markdown', $formatters));
|
||||
$page->assign('SYNTAXHIGHLIGHTING', array_key_exists('syntaxhighlighting', $formatters));
|
||||
$page->assign('SYNTAXHIGHLIGHTINGTHEME', $this->_getMainConfig('syntaxhighlightingtheme', ''));
|
||||
$page->assign('NOTICE', $this->_getMainConfig('notice', ''));
|
||||
$page->assign('FORMATTER', $formatters);
|
||||
$page->assign('FORMATTERDEFAULT', $this->_getMainConfig('defaultformatter', 'plaintext'));
|
||||
$page->assign('NOTICE', i18n::_($this->_getMainConfig('notice', '')));
|
||||
$page->assign('BURNAFTERREADINGSELECTED', $this->_getMainConfig('burnafterreadingselected', false));
|
||||
$page->assign('PASSWORD', $this->_getMainConfig('password', true));
|
||||
$page->assign('FILEUPLOAD', $this->_getMainConfig('fileupload', false));
|
||||
$page->assign('BASE64JSVERSION', $this->_getMainConfig('base64version', '2.1.9'));
|
||||
$page->assign('LANGUAGESELECTION', $languageselection);
|
||||
$page->assign('LANGUAGES', i18n::getLanguageLabels(i18n::getAvailableLanguages()));
|
||||
$page->assign('EXPIRE', $expire);
|
||||
$page->assign('EXPIREDEFAULT', $this->_conf['expire']['default']);
|
||||
$page->draw($this->_getMainConfig('template', 'page'));
|
||||
@@ -629,7 +683,7 @@ class zerobin
|
||||
$result = array('status' => $status);
|
||||
if ($status)
|
||||
{
|
||||
$result['message'] = $message;
|
||||
$result['message'] = i18n::_($message);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @link http://sebsauvage.net/wiki/doku.php?id=php:zerobin
|
||||
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
|
||||
* @version 0.20
|
||||
* @version 0.21
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -183,7 +183,7 @@ class zerobin_db extends zerobin_abstract
|
||||
public function create($pasteid, $paste)
|
||||
{
|
||||
if (
|
||||
array_key_exists($pasteid, self::$_cache)
|
||||
array_key_exists($pasteid, self::$_cache)
|
||||
) {
|
||||
if(false !== self::$_cache[$pasteid]) {
|
||||
return false;
|
||||
|
||||
197
tpl/bootstrap-compact.html
Normal file
197
tpl/bootstrap-compact.html
Normal file
@@ -0,0 +1,197 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="robots" content="noindex" />
|
||||
<title>{function="t('ZeroBin')"}</title>
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.3.5.css" />
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/zerobin.css?{$VERSION|rawurlencode}" />{if="$SYNTAXHIGHLIGHTING"}
|
||||
<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?{$VERSION|rawurlencode}" />{if="strlen($SYNTAXHIGHLIGHTINGTHEME)"}
|
||||
<link type="text/css" rel="stylesheet" href="css/prettify/{$SYNTAXHIGHLIGHTINGTHEME}.css?{$VERSION|rawurlencode}" />{/if}{/if}
|
||||
<script type="text/javascript" src="js/jquery-1.11.3.js"></script>
|
||||
<script type="text/javascript" src="js/sjcl-1.0.2.js"></script>
|
||||
<script type="text/javascript" src="js/base64-{$BASE64JSVERSION}.js"></script>
|
||||
<script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
|
||||
<script type="text/javascript" src="js/rawinflate-0.3.js"></script>
|
||||
<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script>{if="$SYNTAXHIGHLIGHTING"}
|
||||
<script type="text/javascript" src="js/prettify.js?{$VERSION|rawurlencode}"></script>{/if}{if="$MARKDOWN"}
|
||||
<script type="text/javascript" src="js/showdown.js?{$VERSION|rawurlencode}"></script>{/if}
|
||||
<script type="text/javascript" src="js/zerobin.js?{$VERSION|rawurlencode}"></script>
|
||||
<!--[if lt IE 10]>
|
||||
<style type="text/css">#ienotice {display:block !important;} #oldienotice {display:block !important;}</style>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body role="document" class="navbar-spacing">
|
||||
<nav class="navbar navbar-default navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">{function="t('Toggle navigation')"}</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="reloadlink navbar-brand" href="/">{function="t('ZeroBin')"}</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="pr">
|
||||
<button id="sendbutton" type="button" class="hidden btn btn-default navbar-btn">
|
||||
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> {function="t('Send')"}
|
||||
</button>
|
||||
<button id="clonebutton" type="button" class="hidden btn btn-default navbar-btn">
|
||||
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> {function="t('Clone')"}
|
||||
</button>
|
||||
<button id="rawtextbutton" type="button" class="hidden btn btn-default navbar-btn">
|
||||
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> {function="t('Raw text')"}
|
||||
</button>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<select id="pasteExpiration" name="pasteExpiration" class="hidden">
|
||||
{loop="EXPIRE"}
|
||||
<option value="{$key}"{if="$key == $EXPIREDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
|
||||
</select>
|
||||
<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{function="t('Expires')"}: <span id="pasteExpirationDisplay">{$EXPIRE[$EXPIREDEFAULT]}</span> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{loop="EXPIRE"}
|
||||
<li>
|
||||
<a href="#" onclick="$('#pasteExpiration').val('{$key}');$('#pasteExpirationDisplay').text('{$value}');return false;">
|
||||
{$value}
|
||||
</a>
|
||||
</li>{/loop}
|
||||
</ul>
|
||||
</li>
|
||||
<li id="formatter" class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{function="t('Options')"} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li id="burnafterreadingoption" class="checkbox hidden">
|
||||
<label>
|
||||
<input type="checkbox" id="burnafterreading" name="burnafterreading" {if="$BURNAFTERREADINGSELECTED"} checked="checked"{/if} />
|
||||
{function="t('Burn after reading')"}
|
||||
</label>
|
||||
</li>{if="$DISCUSSION"}
|
||||
<li id="opendisc" class="checkbox hidden">
|
||||
<label>
|
||||
<input type="checkbox" id="opendiscussion" name="opendiscussion" {if="$OPENDISCUSSION"} checked="checked"{/if} />
|
||||
{function="t('Open discussion')"}
|
||||
</label>
|
||||
</li>{/if}
|
||||
<li role="separator" class="divider"></li>
|
||||
<li>
|
||||
<div>
|
||||
{function="t('Format')"}: <span id="pasteFormatterDisplay">{$FORMATTER[$FORMATTERDEFAULT]}</span> <span class="caret"></span>
|
||||
</div>
|
||||
</li>
|
||||
{loop="FORMATTER"}
|
||||
<li>
|
||||
<a href="#" onclick="$('#pasteFormatter').val('{$key}');$('#pasteFormatterDisplay').text('{$value}');return false;">
|
||||
{$value}
|
||||
</a>
|
||||
</li>{/loop}
|
||||
</ul>
|
||||
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
|
||||
{loop="FORMATTER"}
|
||||
<option value="{$key}"{if="$key == $FORMATTERDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
|
||||
</select>
|
||||
</li>{if="$PASSWORD"}
|
||||
<li>
|
||||
<div id="password" class="navbar-form hidden">
|
||||
<input type="password" id="passwordinput" placeholder="{function="t('Password (recommended)')"}" class="form-control" size="19"/>
|
||||
</div>
|
||||
</li>{/if}{if="$FILEUPLOAD"}
|
||||
<li id="attach" class="hidden dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{function="t('Attach a file')"} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li id="filewrap">
|
||||
<div>
|
||||
<input type="file" id="file" name="file" />
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<a id="fileremovebutton" href="#">
|
||||
{function="t('Remove attachment')"}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>{/if}
|
||||
</ul>
|
||||
<ul class="nav navbar-nav pull-right">{if="strlen($LANGUAGESELECTION)"}
|
||||
<li id="language" class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> {$LANGUAGES[$LANGUAGESELECTION][0]} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{loop="LANGUAGES"}
|
||||
<li>
|
||||
<a href="#" class="reloadlink" onclick="document.cookie='lang={$key}';">
|
||||
{$value[0]} ({$value[1]})
|
||||
</a>
|
||||
</li>{/loop}
|
||||
</ul>
|
||||
</li>{/if}
|
||||
<li>
|
||||
<button id="newbutton" type="button" class="reloadlink hidden btn btn-default navbar-btn">
|
||||
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> {function="t('New')"}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<header class="container">{if="strlen($NOTICE)"}
|
||||
<div role="alert" class="alert alert-info">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> {$NOTICE|htmlspecialchars}
|
||||
</div>{/if}
|
||||
<div id="remainingtime" role="alert" class="hidden alert alert-info">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
|
||||
</div>{if="$FILEUPLOAD"}
|
||||
<div id="attachment" role="alert" class="hidden alert alert-info">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a>{function="t('Download attachment')"}</a> <span id="clonedfile" class="hidden">{function="t('Cloned file attached.')"}</span>
|
||||
</div>{/if}{if="strlen($STATUS)"}
|
||||
<div id="status" role="alert" class="alert alert-success">
|
||||
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> {$STATUS|htmlspecialchars}
|
||||
</div>{/if}
|
||||
<div id="errormessage" role="alert" class="{if="!strlen($ERROR)"}hidden {/if}alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> {$ERROR|htmlspecialchars}</div>
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> {function="t('Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.')"}</div>
|
||||
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> {function="t('ZeroBin requires a modern browser to work.')"}</div>
|
||||
<div id="ienotice" role="alert" class="hidden alert alert-warning"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> {function="t('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:')"}
|
||||
<a href="http://www.mozilla.org/firefox/">Firefox</a>,
|
||||
<a href="http://www.opera.com/">Opera</a>,
|
||||
<a href="http://www.google.com/chrome">Chrome</a>,
|
||||
<a href="http://www.apple.com/safari">Safari</a>...
|
||||
</div>
|
||||
<div id="pasteresult" role="alert" class="hidden alert alert-success">
|
||||
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
|
||||
<div id="deletelink"></div>
|
||||
<div id="pastelink"></div>
|
||||
</div>
|
||||
</header>
|
||||
<section class="container">
|
||||
<article class="row">
|
||||
<div id="image" class="col-md-12 text-center hidden"></div>
|
||||
<div id="prettymessage" class="col-md-12 hidden">
|
||||
<pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre>
|
||||
</div>
|
||||
<div id="cleartext" class="col-md-12 hidden"></div>
|
||||
<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
|
||||
</article>
|
||||
</section>
|
||||
<section class="container">
|
||||
<div id="discussion" class="hidden">
|
||||
<h4>{function="t('Discussion')"}</h4>
|
||||
<div id="comments"></div>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="container">
|
||||
<div class="row">
|
||||
<h4 class="col-md-5 col-xs-8">{function="t('ZeroBin')"} <small>- {function="t('Because ignorance is bliss')"}</small></h4>
|
||||
<p class="col-md-1 col-xs-4 text-center">{$VERSION}</p>
|
||||
<p id="aboutbox" class="col-md-6 col-xs-12">
|
||||
{function="t('ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/elrido/ZeroBin/wiki">project page</a>.')"}
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="cipherdata" class="hidden">{$CIPHERDATA}</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="robots" content="noindex" />
|
||||
<title>ZeroBin</title>
|
||||
<title>{function="t('ZeroBin')"}</title>
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.3.5.css" />
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.3.5.css" />
|
||||
<link type="text/css" rel="stylesheet" href="css/bootstrap/zerobin.css?{$VERSION|rawurlencode}" />{if="$SYNTAXHIGHLIGHTING"}
|
||||
@@ -17,42 +17,36 @@
|
||||
<script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
|
||||
<script type="text/javascript" src="js/rawinflate-0.3.js"></script>
|
||||
<script type="text/javascript" src="js/bootstrap-3.3.5.js"></script>{if="$SYNTAXHIGHLIGHTING"}
|
||||
<script type="text/javascript" src="js/prettify.js?{$VERSION|rawurlencode}"></script>{/if}
|
||||
<script type="text/javascript" src="js/prettify.js?{$VERSION|rawurlencode}"></script>{/if}{if="$MARKDOWN"}
|
||||
<script type="text/javascript" src="js/showdown.js?{$VERSION|rawurlencode}"></script>{/if}
|
||||
<script type="text/javascript" src="js/zerobin.js?{$VERSION|rawurlencode}"></script>
|
||||
<!--[if lt IE 10]>
|
||||
<style type="text/css">#ienotice {display:block !important;} #oldienotice {display:block !important;}</style>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body role="document">
|
||||
<nav class="navbar navbar-default navbar-fixed-top">
|
||||
<nav class="navbar navbar-default navbar-static-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="sr-only">{function="t('Toggle navigation')"}</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/" onclick="window.location.href=scriptLocation();return false;">ZeroBin</a>
|
||||
<a class="reloadlink navbar-brand" href="/">{function="t('ZeroBin')"}</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav pull-right">
|
||||
<li>
|
||||
<button id="newbutton" type="button" class="hidden btn btn-default navbar-btn" onclick="window.location.href=scriptLocation();return false;">
|
||||
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> New
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="pr">
|
||||
<button id="sendbutton" type="button" class="hidden btn btn-default navbar-btn" onclick="send_data();return false;">
|
||||
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Send
|
||||
<button id="sendbutton" type="button" class="hidden btn btn-default navbar-btn">
|
||||
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> {function="t('Send')"}
|
||||
</button>
|
||||
<button id="clonebutton" type="button" class="hidden btn btn-default navbar-btn" onclick="clonePaste();return false;">
|
||||
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> Clone
|
||||
<button id="clonebutton" type="button" class="hidden btn btn-default navbar-btn">
|
||||
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> {function="t('Clone')"}
|
||||
</button>
|
||||
<button id="rawtextbutton" type="button" class="hidden btn btn-default navbar-btn" onclick="rawText();return false;">
|
||||
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> Raw text
|
||||
<button id="rawtextbutton" type="button" class="hidden btn btn-default navbar-btn">
|
||||
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> {function="t('Raw text')"}
|
||||
</button>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
@@ -60,17 +54,21 @@
|
||||
{loop="EXPIRE"}
|
||||
<option value="{$key}"{if="$key == $EXPIREDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
|
||||
</select>
|
||||
<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Expires: <span id="pasteExpirationDisplay">{$EXPIREDEFAULT}</span> <span class="caret"></span></a>
|
||||
<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{function="t('Expires')"}: <span id="pasteExpirationDisplay">{$EXPIRE[$EXPIREDEFAULT]}</span> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{loop="EXPIRE"}
|
||||
<li><a href="#" onclick="$('#pasteExpiration').val('{$key}');$('#pasteExpirationDisplay').text('{$value}');return false;">{$value}</a></li>{/loop}
|
||||
<li>
|
||||
<a href="#" onclick="$('#pasteExpiration').val('{$key}');$('#pasteExpirationDisplay').text('{$value}');return false;">
|
||||
{$value}
|
||||
</a>
|
||||
</li>{/loop}
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<div id="burnafterreadingoption" class="navbar-text checkbox hidden">
|
||||
<label>
|
||||
<input type="checkbox" id="burnafterreading" name="burnafterreading" {if="$BURNAFTERREADINGSELECTED"} checked="checked"{/if} />
|
||||
Burn after reading
|
||||
{function="t('Burn after reading')"}
|
||||
</label>
|
||||
</div>
|
||||
</li>{if="$DISCUSSION"}
|
||||
@@ -78,17 +76,62 @@
|
||||
<div id="opendisc" class="navbar-text checkbox hidden">
|
||||
<label>
|
||||
<input type="checkbox" id="opendiscussion" name="opendiscussion" {if="$OPENDISCUSSION"} checked="checked"{/if} />
|
||||
Open discussion
|
||||
{function="t('Open discussion')"}
|
||||
</label>
|
||||
</div>
|
||||
</li>{/if}{if="$PASSWORD"}
|
||||
<li>
|
||||
<div id="password" class="navbar-form hidden">
|
||||
<input type="password" id="passwordinput" placeholder="Password (optional)" class="form-control" size="19"/>
|
||||
<input type="password" id="passwordinput" placeholder="{function="t('Password (recommended)')"}" class="form-control" size="19"/>
|
||||
</div>
|
||||
</li>{/if}{if="$FILEUPLOAD"}
|
||||
<li id="attach" class="hidden dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{function="t('Attach a file')"} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li id="filewrap">
|
||||
<div>
|
||||
<input type="file" id="file" name="file" />
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<a id="fileremovebutton" href="#">
|
||||
{function="t('Remove attachment')"}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>{/if}
|
||||
<li class="dropdown">
|
||||
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
|
||||
{loop="FORMATTER"}
|
||||
<option value="{$key}"{if="$key == $FORMATTERDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
|
||||
</select>
|
||||
<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{function="t('Format')"}: <span id="pasteFormatterDisplay">{$FORMATTER[$FORMATTERDEFAULT]}</span> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{loop="FORMATTER"}
|
||||
<li>
|
||||
<a href="#" onclick="$('#pasteFormatter').val('{$key}');$('#pasteFormatterDisplay').text('{$value}');return false;">
|
||||
{$value}
|
||||
</a>
|
||||
</li>{/loop}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav pull-right">{if="strlen($LANGUAGESELECTION)"}
|
||||
<li id="language" class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> {$LANGUAGES[$LANGUAGESELECTION][0]} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{loop="LANGUAGES"}
|
||||
<li>
|
||||
<a href="#" class="reloadlink" onclick="document.cookie='lang={$key}';">
|
||||
{$value[0]} ({$value[1]})
|
||||
</a>
|
||||
</li>{/loop}
|
||||
</ul>
|
||||
</li>{/if}
|
||||
<li>
|
||||
<p id="remainingtime" class="hidden navbar-text"></p>
|
||||
<button id="newbutton" type="button" class="reloadlink hidden btn btn-default navbar-btn">
|
||||
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> {function="t('New')"}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -97,12 +140,20 @@
|
||||
<header class="container">{if="strlen($NOTICE)"}
|
||||
<div role="alert" class="alert alert-info">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> {$NOTICE|htmlspecialchars}
|
||||
</div>{/if}
|
||||
<div id="remainingtime" role="alert" class="hidden alert alert-info">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
|
||||
</div>{if="$FILEUPLOAD"}
|
||||
<div id="attachment" role="alert" class="hidden alert alert-info">
|
||||
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> <a>{function="t('Download attachment')"}</a> <span id="clonedfile" class="hidden">{function="t('Cloned file attached.')"}</span>
|
||||
</div>{/if}{if="strlen($STATUS)"}
|
||||
<div id="status" role="alert" class="alert alert-success"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span> {$STATUS|htmlspecialchars}</div>{/if}
|
||||
<div id="status" role="alert" class="alert alert-success">
|
||||
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> {$STATUS|htmlspecialchars}
|
||||
</div>{/if}
|
||||
<div id="errormessage" role="alert" class="{if="!strlen($ERROR)"}hidden {/if}alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> {$ERROR|htmlspecialchars}</div>
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.</div>
|
||||
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> ZeroBin requires a modern browser to work.</div>
|
||||
<div id="ienotice" role="alert" class="hidden alert alert-warning"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> Still using Internet Explorer? Do yourself a favor, switch to a modern browser:
|
||||
<div id="noscript" role="alert" class="nonworking alert alert-warning"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> {function="t('Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.')"}</div>
|
||||
<div id="oldienotice" role="alert" class="hidden nonworking alert alert-danger"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> {function="t('ZeroBin requires a modern browser to work.')"}</div>
|
||||
<div id="ienotice" role="alert" class="hidden alert alert-warning"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> {function="t('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:')"}
|
||||
<a href="http://www.mozilla.org/firefox/">Firefox</a>,
|
||||
<a href="http://www.opera.com/">Opera</a>,
|
||||
<a href="http://www.google.com/chrome">Chrome</a>,
|
||||
@@ -116,6 +167,7 @@
|
||||
</header>
|
||||
<section class="container">
|
||||
<article class="row">
|
||||
<div id="image" class="col-md-12 text-center hidden"></div>
|
||||
<div id="prettymessage" class="col-md-12 hidden">
|
||||
<pre id="prettyprint" class="col-md-12 prettyprint linenums:1"></pre>
|
||||
</div>
|
||||
@@ -125,18 +177,16 @@
|
||||
</section>
|
||||
<section class="container">
|
||||
<div id="discussion" class="hidden">
|
||||
<h4>Discussion</h4>
|
||||
<h4>{function="t('Discussion')"}</h4>
|
||||
<div id="comments"></div>
|
||||
</div>
|
||||
</section>
|
||||
<footer class="container">
|
||||
<div class="row">
|
||||
<h4 class="col-md-3 col-xs-8">ZeroBin <small>- Because ignorance is bliss</small></h4>
|
||||
<h4 class="col-md-5 col-xs-8">{function="t('ZeroBin')"} <small>- {function="t('Because ignorance is bliss')"}</small></h4>
|
||||
<p class="col-md-1 col-xs-4 text-center">{$VERSION}</p>
|
||||
<p id="aboutbox" class="col-md-8 col-xs-12">
|
||||
ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data.<br />
|
||||
Data is encrypted/decrypted <em>in the browser</em> using 256 bits AES.<br />
|
||||
More information on the <a href="http://sebsauvage.net/wiki/doku.php?id=php:zerobin" target="_blank">project page</a>.
|
||||
<p id="aboutbox" class="col-md-6 col-xs-12">
|
||||
{function="t('ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/elrido/ZeroBin/wiki">project page</a>.')"}
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="robots" content="noindex" />
|
||||
<title>ZeroBin</title>
|
||||
<title>{function="t('ZeroBin')"}</title>
|
||||
<link type="text/css" rel="stylesheet" href="css/zerobin.css?{$VERSION|rawurlencode}" />{if="$SYNTAXHIGHLIGHTING"}
|
||||
<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?{$VERSION|rawurlencode}" />{if="strlen($SYNTAXHIGHLIGHTINGTHEME)"}
|
||||
<link type="text/css" rel="stylesheet" href="css/prettify/{$SYNTAXHIGHLIGHTINGTHEME}.css?{$VERSION|rawurlencode}" />{/if}{/if}
|
||||
@@ -12,7 +12,8 @@
|
||||
<script type="text/javascript" src="js/base64-{$BASE64JSVERSION}.js"></script>
|
||||
<script type="text/javascript" src="js/rawdeflate-0.5.js"></script>
|
||||
<script type="text/javascript" src="js/rawinflate-0.3.js"></script>{if="$SYNTAXHIGHLIGHTING"}
|
||||
<script type="text/javascript" src="js/prettify.js?{$VERSION|rawurlencode}"></script>{/if}
|
||||
<script type="text/javascript" src="js/prettify.js?{$VERSION|rawurlencode}"></script>{/if}{if="$MARKDOWN"}
|
||||
<script type="text/javascript" src="js/showdown.js?{$VERSION|rawurlencode}"></script>{/if}
|
||||
<script type="text/javascript" src="js/zerobin.js?{$VERSION|rawurlencode}"></script>
|
||||
<!--[if lt IE 10]>
|
||||
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;} #oldienotice {display:block;}</style>
|
||||
@@ -21,17 +22,15 @@
|
||||
<body>
|
||||
<header>
|
||||
<div id="aboutbox">
|
||||
ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data.
|
||||
Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES.
|
||||
More information on the <a href="http://sebsauvage.net/wiki/doku.php?id=php:zerobin">project page</a>.<br />{if="strlen($NOTICE)"}
|
||||
{function="t('ZeroBin is a minimalist, opensource online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://github.com/elrido/ZeroBin/wiki">project page</a>.')"}<br />{if="strlen($NOTICE)"}
|
||||
<span class="blink">▶</span> {$NOTICE}{/if}
|
||||
</div>
|
||||
<h1 title="ZeroBin" onclick="window.location.href=scriptLocation();return false;">ZeroBin</h1><br />
|
||||
<h2>Because ignorance is bliss</h2><br />
|
||||
<h3>{$VERSION}</h3>
|
||||
<div id="noscript" class="nonworking">Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.</div>
|
||||
<div id="oldienotice" class="nonworking">ZeroBin requires a modern browser to work.</div>
|
||||
<div id="ienotice">Still using Internet Explorer ? Do yourself a favor, switch to a modern browser:
|
||||
<h1 class="title reloadlink">{function="t('ZeroBin')"}</h1><br />
|
||||
<h2 class="title">{function="t('Because ignorance is bliss')"}</h2><br />
|
||||
<h3 class="title">{$VERSION}</h3>
|
||||
<div id="noscript" class="nonworking">{function="t('Javascript is required for ZeroBin to work.<br />Sorry for the inconvenience.')"}</div>
|
||||
<div id="oldienotice" class="nonworking">{function="t('ZeroBin requires a modern browser to work.')"}</div>
|
||||
<div id="ienotice">{function="t('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:')"}
|
||||
<a href="http://www.mozilla.org/firefox/">Firefox</a>,
|
||||
<a href="http://www.opera.com/">Opera</a>,
|
||||
<a href="http://www.google.com/chrome">Chrome</a>,
|
||||
@@ -43,11 +42,11 @@
|
||||
<div id="status">{$STATUS|htmlspecialchars}</div>
|
||||
<div id="errormessage" class="hidden">{$ERROR|htmlspecialchars}</div>
|
||||
<div id="toolbar">
|
||||
<button id="newbutton" onclick="window.location.href=scriptLocation();return false;" class="hidden"><img src="img/icon_new.png" width="11" height="15" alt="" />New</button>
|
||||
<button id="sendbutton" onclick="send_data();return false;" class="hidden"><img src="img/icon_send.png" width="18" height="15" alt="" />Send</button>
|
||||
<button id="clonebutton" onclick="clonePaste();return false;" class="hidden"><img src="img/icon_clone.png" width="15" height="17" alt="" />Clone</button>
|
||||
<button id="rawtextbutton" onclick="rawText();return false;" class="hidden"><img src="img/icon_raw.png" width="15" height="15" alt="" />Raw text</button>
|
||||
<div id="expiration" class="hidden">Expires:
|
||||
<button id="newbutton" class="reloadlink hidden"><img src="img/icon_new.png" width="11" height="15" alt="" />{function="t('New')"}</button>
|
||||
<button id="sendbutton" class="hidden"><img src="img/icon_send.png" width="18" height="15" alt="" />{function="t('Send')"}</button>
|
||||
<button id="clonebutton" class="hidden"><img src="img/icon_clone.png" width="15" height="17" alt="" />{function="t('Clone')"}</button>
|
||||
<button id="rawtextbutton" class="hidden"><img src="img/icon_raw.png" width="15" height="15" alt="" />{function="t('Raw text')"}</button>
|
||||
<div id="expiration" class="hidden button">{function="t('Expires')"}:
|
||||
<select id="pasteExpiration" name="pasteExpiration">
|
||||
{loop="EXPIRE"}
|
||||
<option value="{$key}"{if="$key == $EXPIREDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
|
||||
@@ -56,20 +55,39 @@
|
||||
<div id="remainingtime" class="hidden"></div>
|
||||
<div id="burnafterreadingoption" class="button hidden">
|
||||
<input type="checkbox" id="burnafterreading" name="burnafterreading" {if="$BURNAFTERREADINGSELECTED"} checked="checked"{/if} />
|
||||
<label for="burnafterreading">Burn after reading</label>
|
||||
<label for="burnafterreading">{function="t('Burn after reading')"}</label>
|
||||
</div>{if="$DISCUSSION"}
|
||||
<div id="opendisc" class="button hidden">
|
||||
<input type="checkbox" id="opendiscussion" name="opendiscussion" {if="$OPENDISCUSSION"} checked="checked"{/if} />
|
||||
<label for="opendiscussion" {if="!$OPENDISCUSSION"} style="color: #BBBBBB;"{/if}>Open discussion</label>
|
||||
<label for="opendiscussion" {if="!$OPENDISCUSSION"} style="color: #BBBBBB;"{/if}>{function="t('Open discussion')"}</label>
|
||||
</div>{/if}{if="$PASSWORD"}
|
||||
<div id="password" class="hidden">
|
||||
<input id="passwordinput" placeholder="Optional password (recommended)" size="32" />
|
||||
<input type="password" id="passwordinput" placeholder="{function="t('Password (recommended)')"}" size="32" />
|
||||
</div>{/if}
|
||||
<div id="formatter" class="button hidden">{function="t('Format')"}:
|
||||
<select id="pasteFormatter" name="pasteFormatter">
|
||||
{loop="FORMATTER"}
|
||||
<option value="{$key}"{if="$key == $FORMATTERDEFAULT"} selected="selected"{/if}>{$value}</option>{/loop}
|
||||
</select>
|
||||
</div>{if="strlen($LANGUAGESELECTION)"}
|
||||
<div id="language" class="button">
|
||||
<select name="lang">
|
||||
{loop="LANGUAGES"}
|
||||
<option class="reloadlink" onclick="document.cookie='lang={$key}';" value="{$key}"{if="$key == $LANGUAGESELECTION"} selected="selected"{/if}>{$value[0]} ({$value[1]})</option>{/loop}
|
||||
</select>
|
||||
</div>{/if}
|
||||
</div>
|
||||
<div id="pasteresult" class="hidden">
|
||||
<div id="deletelink"></div>
|
||||
<div id="pastelink"></div>
|
||||
</div>
|
||||
</div>{if="$FILEUPLOAD"}
|
||||
<div id="attachment" class="hidden"><a>{function="t('Download attachment')"}</a></div>
|
||||
<div id="attach" class="hidden">
|
||||
<span id="clonedfile" class="hidden">{function="t('Cloned file attached.')"}</span>
|
||||
<span id="filewrap">{function="t('Attach a file')"}: <input type="file" id="file" name="file" /></span>
|
||||
<button id="fileremovebutton">{function="t('Remove attachment')"}</button>
|
||||
</div>{/if}
|
||||
<div id="image" class="hidden"></div>
|
||||
<div id="prettymessage" class="hidden">
|
||||
<pre id="prettyprint" class="prettyprint linenums:1"></pre>
|
||||
</div>
|
||||
@@ -79,7 +97,7 @@
|
||||
</section>
|
||||
<section>
|
||||
<div id="discussion" class="hidden">
|
||||
<h4>Discussion</h4>
|
||||
<h4 class="title">{function="t('Discussion')"}</h4>
|
||||
<div id="comments"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -33,12 +33,16 @@ class RainTPLTest extends PHPUnit_Framework_TestCase
|
||||
$page->assign('VERSION', self::$version);
|
||||
$page->assign('DISCUSSION', true);
|
||||
$page->assign('OPENDISCUSSION', true);
|
||||
$page->assign('MARKDOWN', true);
|
||||
$page->assign('SYNTAXHIGHLIGHTING', true);
|
||||
$page->assign('SYNTAXHIGHLIGHTINGTHEME', 'sons-of-obsidian');
|
||||
$page->assign('BURNAFTERREADINGSELECTED', false);
|
||||
$page->assign('PASSWORD', true);
|
||||
$page->assign('FILEUPLOAD', false);
|
||||
$page->assign('BASE64JSVERSION', '2.1.9');
|
||||
$page->assign('NOTICE', 'example');
|
||||
$page->assign('LANGUAGESELECTION', '');
|
||||
$page->assign('LANGUAGES', i18n::getLanguageLabels(i18n::getAvailableLanguages()));
|
||||
$page->assign('EXPIRE', self::$expire);
|
||||
$page->assign('EXPIREDEFAULT', self::$expire_default);
|
||||
ob_start();
|
||||
|
||||
@@ -3,6 +3,7 @@ error_reporting( E_ALL | E_STRICT );
|
||||
|
||||
// change this, if your php files and data is outside of your webservers document root
|
||||
if (!defined('PATH')) define('PATH', '..' . DIRECTORY_SEPARATOR);
|
||||
if (!defined('PUBLIC_PATH')) define('PUBLIC_PATH', '..');
|
||||
|
||||
require PATH . 'lib/auto.php';
|
||||
|
||||
|
||||
@@ -9,14 +9,31 @@ class filterTest extends PHPUnit_Framework_TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testFilterMakesTimesHumanlyReadable()
|
||||
{
|
||||
$this->assertEquals('5 minutes', filter::time_humanreadable('5min'));
|
||||
$this->assertEquals('90 seconds', filter::time_humanreadable('90sec'));
|
||||
$this->assertEquals('1 week', filter::time_humanreadable('1week'));
|
||||
$this->assertEquals('6 months', filter::time_humanreadable('6months'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionCode 30
|
||||
*/
|
||||
public function testFilterFailTimesHumanlyReadable()
|
||||
{
|
||||
filter::time_humanreadable('five_minutes');
|
||||
}
|
||||
|
||||
public function testFilterMakesSizesHumanlyReadable()
|
||||
{
|
||||
$this->assertEquals('1 B', filter::size_humanreadable(1));
|
||||
$this->assertEquals('1 000 B', filter::size_humanreadable(1000));
|
||||
$this->assertEquals('1.00 kiB', filter::size_humanreadable(1024));
|
||||
$this->assertEquals('1.21 kiB', filter::size_humanreadable(1234));
|
||||
$this->assertEquals('1.00 KiB', filter::size_humanreadable(1024));
|
||||
$this->assertEquals('1.21 KiB', filter::size_humanreadable(1234));
|
||||
$exponent = 1024;
|
||||
$this->assertEquals('1 000.00 kiB', filter::size_humanreadable(1000 * $exponent));
|
||||
$this->assertEquals('1 000.00 KiB', filter::size_humanreadable(1000 * $exponent));
|
||||
$this->assertEquals('1.00 MiB', filter::size_humanreadable(1024 * $exponent));
|
||||
$this->assertEquals('1.21 MiB', filter::size_humanreadable(1234 * $exponent));
|
||||
$exponent *= 1024;
|
||||
|
||||
79
tst/i18n.php
Normal file
79
tst/i18n.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
class i18nTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $_translations = array();
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
/* Setup Routine */
|
||||
$this->_translations = json_decode(
|
||||
file_get_contents(PATH . 'i18n' . DIRECTORY_SEPARATOR . 'de.json'),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
/* Tear Down Routine */
|
||||
}
|
||||
|
||||
public function testTranslationFallback()
|
||||
{
|
||||
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'foobar';
|
||||
$messageId = 'It does not matter if the message ID exists';
|
||||
i18n::loadTranslations();
|
||||
$this->assertEquals($messageId, i18n::_($messageId), 'fallback to en');
|
||||
}
|
||||
|
||||
public function testCookieLanguageDeDetection()
|
||||
{
|
||||
$_COOKIE['lang'] = 'de';
|
||||
i18n::loadTranslations();
|
||||
$this->assertEquals($this->_translations['en'], i18n::_('en'), 'browser language de');
|
||||
$this->assertEquals('0 Stunden', i18n::_('%d hours', 0), '0 hours in german');
|
||||
$this->assertEquals('1 Stunde', i18n::_('%d hours', 1), '1 hour in german');
|
||||
$this->assertEquals('2 Stunden', i18n::_('%d hours', 2), '2 hours in french');
|
||||
}
|
||||
|
||||
public function testBrowserLanguageDeDetection()
|
||||
{
|
||||
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-CH,de;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
|
||||
i18n::loadTranslations();
|
||||
$this->assertEquals($this->_translations['en'], i18n::_('en'), 'browser language de');
|
||||
$this->assertEquals('0 Stunden', i18n::_('%d hours', 0), '0 hours in german');
|
||||
$this->assertEquals('1 Stunde', i18n::_('%d hours', 1), '1 hour in german');
|
||||
$this->assertEquals('2 Stunden', i18n::_('%d hours', 2), '2 hours in french');
|
||||
}
|
||||
|
||||
public function testBrowserLanguageFrDetection()
|
||||
{
|
||||
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'fr-CH,fr;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
|
||||
i18n::loadTranslations();
|
||||
$this->assertEquals('fr', i18n::_('en'), 'browser language fr');
|
||||
$this->assertEquals('0 heure', i18n::_('%d hours', 0), '0 hours in french');
|
||||
$this->assertEquals('1 heure', i18n::_('%d hours', 1), '1 hour in french');
|
||||
$this->assertEquals('2 heures', i18n::_('%d hours', 2), '2 hours in french');
|
||||
}
|
||||
|
||||
public function testBrowserLanguagePlDetection()
|
||||
{
|
||||
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'pl;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2';
|
||||
i18n::loadTranslations();
|
||||
$this->assertEquals('pl', i18n::_('en'), 'browser language pl');
|
||||
$this->assertEquals('2 godzina', i18n::_('%d hours', 2), 'hours in polish');
|
||||
}
|
||||
|
||||
public function testBrowserLanguageAnyDetection()
|
||||
{
|
||||
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = '*';
|
||||
i18n::loadTranslations();
|
||||
$this->assertTrue(strlen(i18n::_('en')) == 2, 'browser language any');
|
||||
}
|
||||
|
||||
public function testVariableInjection()
|
||||
{
|
||||
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'foobar';
|
||||
i18n::loadTranslations();
|
||||
$this->assertEquals('some string + 1', i18n::_('some %s + %d', 'string', 1), 'browser language en');
|
||||
}
|
||||
}
|
||||
152
tst/zerobin.php
152
tst/zerobin.php
@@ -8,6 +8,7 @@ class zerobinTest extends PHPUnit_Framework_TestCase
|
||||
'meta' => array(
|
||||
'postdate' => 1344803344,
|
||||
'opendiscussion' => true,
|
||||
'formatter' => 'syntaxhighlighting',
|
||||
),
|
||||
);
|
||||
|
||||
@@ -70,6 +71,31 @@ class zerobinTest extends PHPUnit_Framework_TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testViewLanguageSelection()
|
||||
{
|
||||
$this->reset();
|
||||
$options = parse_ini_file($this->_conf, true);
|
||||
$options['main']['languageselection'] = true;
|
||||
if (!is_file($this->_conf . '.bak') && is_file($this->_conf))
|
||||
rename($this->_conf, $this->_conf . '.bak');
|
||||
helper::createIniFile($this->_conf, $options);
|
||||
$_COOKIE['lang'] = 'de';
|
||||
ob_start();
|
||||
new zerobin;
|
||||
$content = ob_get_contents();
|
||||
$this->assertTag(
|
||||
array(
|
||||
'tag' => 'title',
|
||||
'content' => 'ZeroBin'
|
||||
),
|
||||
$content,
|
||||
'outputs title correctly'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
@@ -108,23 +134,6 @@ class zerobinTest extends PHPUnit_Framework_TestCase
|
||||
$content = ob_get_contents();
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testConfMissingExpireLabel()
|
||||
{
|
||||
$this->reset();
|
||||
$options = parse_ini_file($this->_conf, true);
|
||||
$options['expire_options']['foobar123'] = 10;
|
||||
if (!is_file($this->_conf . '.bak') && is_file($this->_conf))
|
||||
rename($this->_conf, $this->_conf . '.bak');
|
||||
helper::createIniFile($this->_conf, $options);
|
||||
ini_set('magic_quotes_gpc', 1);
|
||||
ob_start();
|
||||
new zerobin;
|
||||
$content = ob_get_contents();
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
@@ -184,6 +193,27 @@ class zerobinTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertFalse($this->_model->exists(self::$pasteid), 'paste exists after posting data');
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testCreateProxyHeader()
|
||||
{
|
||||
$this->reset();
|
||||
$options = parse_ini_file($this->_conf, true);
|
||||
$options['traffic']['header'] = 'X_FORWARDED_FOR';
|
||||
if (!is_file($this->_conf . '.bak') && is_file($this->_conf))
|
||||
rename($this->_conf, $this->_conf . '.bak');
|
||||
helper::createIniFile($this->_conf, $options);
|
||||
$_POST = self::$paste;
|
||||
$_SERVER['HTTP_X_FORWARDED_FOR'] = '::1';
|
||||
ob_start();
|
||||
new zerobin;
|
||||
$content = ob_get_contents();
|
||||
$response = json_decode($content, true);
|
||||
$this->assertEquals(1, $response['status'], 'outputs error status');
|
||||
$this->assertFalse($this->_model->exists(self::$pasteid), 'paste exists after posting data');
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
@@ -219,6 +249,7 @@ class zerobinTest extends PHPUnit_Framework_TestCase
|
||||
helper::createIniFile($this->_conf, $options);
|
||||
$_POST = self::$paste;
|
||||
$_POST['expire'] = '5min';
|
||||
$_POST['formatter'] = 'foo';
|
||||
$_SERVER['REMOTE_ADDR'] = '::1';
|
||||
ob_start();
|
||||
new zerobin;
|
||||
@@ -304,6 +335,35 @@ class zerobinTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertFalse($this->_model->exists(self::$pasteid), 'paste exists after posting data');
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testCreateAttachment()
|
||||
{
|
||||
$this->reset();
|
||||
$options = parse_ini_file($this->_conf, true);
|
||||
$options['traffic']['limit'] = 0;
|
||||
$options['main']['fileupload'] = true;
|
||||
if (!is_file($this->_conf . '.bak') && is_file($this->_conf))
|
||||
rename($this->_conf, $this->_conf . '.bak');
|
||||
helper::createIniFile($this->_conf, $options);
|
||||
$_POST = self::$paste;
|
||||
$_POST['attachment'] = self::$comment['data'];
|
||||
$_POST['attachmentname'] = self::$comment['meta']['nickname'];
|
||||
$_SERVER['REMOTE_ADDR'] = '::1';
|
||||
ob_start();
|
||||
new zerobin;
|
||||
$content = ob_get_contents();
|
||||
$response = json_decode($content, true);
|
||||
$this->assertEquals(0, $response['status'], 'outputs status');
|
||||
$this->assertEquals(
|
||||
hash_hmac('sha1', $response['id'], serversalt::get()),
|
||||
$response['deletetoken'],
|
||||
'outputs valid delete token'
|
||||
);
|
||||
$this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
@@ -461,7 +521,9 @@ class zerobinTest extends PHPUnit_Framework_TestCase
|
||||
if (!is_file($this->_conf . '.bak') && is_file($this->_conf))
|
||||
rename($this->_conf, $this->_conf . '.bak');
|
||||
helper::createIniFile($this->_conf, $options);
|
||||
$this->_model->create(self::$pasteid, self::$paste);
|
||||
$this->_model->createComment(self::$pasteid, self::$pasteid, self::$commentid, self::$comment);
|
||||
$this->assertTrue($this->_model->existsComment(self::$pasteid, self::$pasteid, self::$commentid), 'comment exists before posting data');
|
||||
$_POST = self::$comment;
|
||||
$_POST['pasteid'] = self::$pasteid;
|
||||
$_POST['parentid'] = self::$pasteid;
|
||||
@@ -611,6 +673,55 @@ class zerobinTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(1, $response['status'], 'outputs error status');
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testReadOldSyntax()
|
||||
{
|
||||
$this->reset();
|
||||
$oldPaste = self::$paste;
|
||||
$oldPaste['meta']['syntaxcoloring'] = true;
|
||||
unset($oldPaste['meta']['formatter']);
|
||||
$this->_model->create(self::$pasteid, $oldPaste);
|
||||
$_SERVER['QUERY_STRING'] = self::$pasteid;
|
||||
ob_start();
|
||||
new zerobin;
|
||||
$content = ob_get_contents();
|
||||
$oldPaste['meta']['formatter'] = 'syntaxhighlighting';
|
||||
$this->assertTag(
|
||||
array(
|
||||
'id' => 'cipherdata',
|
||||
'content' => htmlspecialchars(json_encode($oldPaste), ENT_NOQUOTES)
|
||||
),
|
||||
$content,
|
||||
'outputs data correctly'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testReadOldFormat()
|
||||
{
|
||||
$this->reset();
|
||||
$oldPaste = self::$paste;
|
||||
unset($oldPaste['meta']['formatter']);
|
||||
$this->_model->create(self::$pasteid, $oldPaste);
|
||||
$_SERVER['QUERY_STRING'] = self::$pasteid;
|
||||
ob_start();
|
||||
new zerobin;
|
||||
$content = ob_get_contents();
|
||||
$oldPaste['meta']['formatter'] = 'plaintext';
|
||||
$this->assertTag(
|
||||
array(
|
||||
'id' => 'cipherdata',
|
||||
'content' => htmlspecialchars(json_encode($oldPaste), ENT_NOQUOTES)
|
||||
),
|
||||
$content,
|
||||
'outputs data correctly'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
@@ -747,9 +858,12 @@ class zerobinTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
$this->reset();
|
||||
$expiredPaste = self::$paste;
|
||||
$expiredPaste['meta']['expire_date'] = $expiredPaste['meta']['postdate'];
|
||||
$expiredPaste['meta']['expire_date'] = 1000;
|
||||
$this->assertFalse($this->_model->exists(self::$pasteid), 'paste does not exist before being created');
|
||||
$this->_model->create(self::$pasteid, $expiredPaste);
|
||||
$_SERVER['QUERY_STRING'] = self::$pasteid;
|
||||
$this->assertTrue($this->_model->exists(self::$pasteid), 'paste exists before deleting data');
|
||||
$_GET['pasteid'] = self::$pasteid;
|
||||
$_GET['deletetoken'] = 'does not matter in this context, but has to be set';
|
||||
ob_start();
|
||||
new zerobin;
|
||||
$content = ob_get_contents();
|
||||
|
||||
Reference in New Issue
Block a user