diff --git a/doc/README.md b/doc/README.md
index f0bc199..d0ecdbc 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -1,5 +1,5 @@
-Generating documentation
-========================
+Generating PHP documentation
+============================
In order to generate the documentation, you will need to install the following
packages and its dependencies:
@@ -12,7 +12,7 @@ can be found in that projects documentation.
Example for Debian and Ubuntu:
```console
-$ sudo aptitude install php-pear graphviz
+$ sudo apt install php-pear graphviz
$ sudo pear channel-discover pear.phpdoc.org
$ sudo pear install phpdoc/phpDocumentor
```
@@ -20,10 +20,41 @@ $ sudo pear install phpdoc/phpDocumentor
To generate the documentation, change into the main directory and run phpdoc:
```console
$ cd PrivateBin
-$ phpdoc -d lib/ -t doc/
+$ phpdoc -t doc/phpdoc -d lib/
```
**Note:** When used with PHP 7, the prerelease of phpDocumentator 2.9 needs to be
manually installed by downloading it from
[GitHub](https://github.com/phpDocumentor/phpDocumentor2/releases/download/v2.9.0/phpDocumentor.phar)
and then manually moving it to e.g. `/usr/local/bin` and making it executable.
+
+Generating JS documentation
+============================
+
+In order to generate the documentation, you will need to install the following
+packages and its dependencies:
+* npm
+
+Then you can use the node package manager to install the latest stable release
+of jsdoc globally:
+
+```console
+$ npm install -g jsdoc
+```
+
+Example for Debian and Ubuntu, including steps to allow current user to install
+node modules globally:
+```console
+$ sudo apt install npm
+$ sudo mkdir /usr/local/lib/node_modules
+$ sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
+$ npm install -g jsdoc
+$ ln -s /usr/bin/nodejs /usr/local/bin/node
+```
+
+To generate the documentation, change into the main directory and run phpdoc:
+```console
+$ cd PrivateBin
+$ jsdoc -d doc/jsdoc js/privatebin.js
+```
+
diff --git a/js/privatebin.js b/js/privatebin.js
index 60e2775..c79c817 100644
--- a/js/privatebin.js
+++ b/js/privatebin.js
@@ -3,10 +3,12 @@
*
* a zero-knowledge paste bin
*
- * @link https://github.com/PrivateBin/PrivateBin
- * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
- * @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
+ * @see {@link https://github.com/PrivateBin/PrivateBin}
+ * @copyright 2012 Sébastien SAUVAGE ({@link http://sebsauvage.net})
+ * @license {@link https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License}
* @version 1.1
+ * @name PrivateBin
+ * @namespace
*/
'use strict';
@@ -26,13 +28,18 @@ sjcl.random.startCollectors();
$(function() {
/**
* static helper methods
+ *
+ * @name helper
+ * @class
*/
var helper = {
/**
- * Converts a duration (in seconds) into human friendly approximation.
+ * converts a duration (in seconds) into human friendly approximation
*
- * @param int seconds
- * @return array
+ * @name helper.secondsToHuman
+ * @function
+ * @param {number} seconds
+ * @return {Array}
*/
secondsToHuman: function(seconds)
{
@@ -63,11 +70,13 @@ $(function() {
},
/**
- * Converts an associative array to an encoded string
- * for appending to the anchor.
+ * converts an associative array to an encoded string
+ * for appending to the anchor
*
- * @param object associative_array Object to be serialized
- * @return string
+ * @name helper.hashToParameterString
+ * @function
+ * @param {Object} associative_array - Object to be serialized
+ * @return {string}
*/
hashToParameterString: function(associativeArray)
{
@@ -92,10 +101,12 @@ $(function() {
},
/**
- * Converts a string to an associative array.
+ * converts a anchor string to an associative array
*
- * @param string parameter_string String containing parameters
- * @return object
+ * @name helper.parameterStringToHash
+ * @function
+ * @param {string} parameter_string - String containing parameters
+ * @return {Object}
*/
parameterStringToHash: function(parameterString)
{
@@ -113,9 +124,11 @@ $(function() {
},
/**
- * Get an associative array of the parameters found in the anchor
+ * get an associative array of the parameters found in the anchor
*
- * @return object
+ * @name helper.getParameterHash
+ * @function
+ * @return {Object}
*/
getParameterHash: function()
{
@@ -131,10 +144,12 @@ $(function() {
},
/**
- * Text range selection.
- * From: https://stackoverflow.com/questions/985272/jquery-selecting-text-in-an-element-akin-to-highlighting-with-your-mouse
+ * text range selection
*
- * @param string element : Indentifier of the element to select (id="").
+ * @see {@link https://stackoverflow.com/questions/985272/jquery-selecting-text-in-an-element-akin-to-highlighting-with-your-mouse}
+ * @name helper.selectText
+ * @function
+ * @param {string} element - Indentifier of the element to select (id="")
*/
selectText: function(element)
{
@@ -162,11 +177,13 @@ $(function() {
},
/**
- * Set text of a DOM element (required for IE)
- * This is equivalent to element.text(text)
+ * set text of a DOM element (required for IE),
+ * this is equivalent to element.text(text)
*
- * @param object element : a DOM element.
- * @param string text : the text to enter.
+ * @name helper.setElementText
+ * @function
+ * @param {Object} element - a DOM element
+ * @param {string} text - the text to enter
*/
setElementText: function(element, text)
{
@@ -185,8 +202,10 @@ $(function() {
/**
* replace last child of element with message
*
- * @param object element : a jQuery wrapped DOM element.
- * @param string message : the message to append.
+ * @name helper.setMessage
+ * @function
+ * @param {Object} element - a jQuery wrapped DOM element
+ * @param {string} message - the message to append
*/
setMessage: function(element, message)
{
@@ -202,15 +221,17 @@ $(function() {
},
/**
- * Convert URLs to clickable links.
+ * convert URLs to clickable links.
* URLs to handle:
- *
+ *
+ * http://example.com:8800/zero/?6f09182b8ea51997#WtLEUO5Epj9UHAV9JFs+6pUQZp13TuspAUjnF+iM+dM=
+ * http://user:example.com@localhost:8800/zero/?6f09182b8ea51997#WtLEUO5Epj9UHAV9JFs+6pUQZp13TuspAUjnF+iM+dM=
+ *
*
- * @param object element : a jQuery DOM element.
+ * @name helper.urls2links
+ * @function
+ * @param {Object} element - a jQuery DOM element
*/
urls2links: function(element)
{
@@ -231,11 +252,13 @@ $(function() {
/**
* minimal sprintf emulation for %s and %d formats
- * From: https://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format#4795914
*
- * @param string format
- * @param mixed args one or multiple parameters injected into format string
- * @return string
+ * @see {@link https://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format#4795914}
+ * @name helper.sprintf
+ * @function
+ * @param {string} format
+ * @param {...*} args - one or multiple parameters injected into format string
+ * @return {string}
*/
sprintf: function()
{
@@ -273,10 +296,12 @@ $(function() {
/**
* get value of cookie, if it was set, empty string otherwise
- * From: http://www.w3schools.com/js/js_cookies.asp
*
- * @param string cname
- * @return string
+ * @see {@link http://www.w3schools.com/js/js_cookies.asp}
+ * @name helper.getCookie
+ * @function
+ * @param {string} cname
+ * @return {string}
*/
getCookie: function(cname) {
var name = cname + '=';
@@ -293,12 +318,13 @@ $(function() {
},
/**
- * Convert all applicable characters to HTML entities.
- * From: https://github.com/janl/mustache.js/blob/master/mustache.js#L60
- * Also: https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content
+ * convert all applicable characters to HTML entities
*
- * @param string str
- * @return string escaped HTML
+ * @see {@link https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content}
+ * @name helper.htmlEntities
+ * @function
+ * @param {string} str
+ * @return {string} escaped HTML
*/
htmlEntities: function(str) {
return String(str).replace(
@@ -309,6 +335,11 @@ $(function() {
/**
* character to HTML entity lookup table
+ *
+ * @see {@link https://github.com/janl/mustache.js/blob/master/mustache.js#L60}
+ * @name helper.entityMap
+ * @enum {Object}
+ * @readonly
*/
entityMap: {
'&': '&',
@@ -324,19 +355,28 @@ $(function() {
/**
* internationalization methods
+ *
+ * @name i18n
+ * @class
*/
var i18n = {
/**
* supported languages, minus the built in 'en'
+ *
+ * @name i18n.supportedLanguages
+ * @prop {string[]}
+ * @readonly
*/
supportedLanguages: ['de', 'es', 'fr', 'it', 'no', 'pl', 'oc', 'ru', 'sl', 'zh'],
/**
- * translate a string, alias for translate()
+ * translate a string, alias for i18n.translate()
*
- * @param string $messageId
- * @param mixed args one or multiple parameters injected into placeholders
- * @return string
+ * @name i18n._
+ * @function
+ * @param {string} messageId
+ * @param {...*} args - one or multiple parameters injected into placeholders
+ * @return {string}
*/
_: function()
{
@@ -346,9 +386,11 @@ $(function() {
/**
* translate a string
*
- * @param string $messageId
- * @param mixed args one or multiple parameters injected into placeholders
- * @return string
+ * @name i18n.translate
+ * @function
+ * @param {string} messageId
+ * @param {...*} args - one or multiple parameters injected into placeholders
+ * @return {string}
*/
translate: function()
{
@@ -402,10 +444,12 @@ $(function() {
/**
* per language functions to use to determine the plural form
- * From: http://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html
*
- * @param int number
- * @return int array key
+ * @see {@link http://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html}
+ * @name i18n.getPluralForm
+ * @function
+ * @param {number} n
+ * @return {number} array key
*/
getPluralForm: function(n) {
switch (this.language)
@@ -429,7 +473,9 @@ $(function() {
/**
* load translations into cache, then execute callback function
*
- * @param function callback
+ * @name i18n.loadTranslations
+ * @function
+ * @param {Function} callback
*/
loadTranslations: function(callback)
{
@@ -452,24 +498,35 @@ $(function() {
/**
* built in language
+ *
+ * @name i18n.language
+ * @prop {string}
*/
language: 'en',
/**
* translation cache
+ *
+ * @name i18n.translations
+ * @enum {Object}
*/
translations: {}
};
/**
* filter methods
+ *
+ * @name filter
+ * @class
*/
var filter = {
/**
- * Compress a message (deflate compression). Returns base64 encoded data.
+ * compress a message (deflate compression), returns base64 encoded data
*
- * @param string message
- * @return base64 string data
+ * @name filter.compress
+ * @function
+ * @param {string} message
+ * @return {string} base64 data
*/
compress: function(message)
{
@@ -477,10 +534,12 @@ $(function() {
},
/**
- * Decompress a message compressed with compress().
+ * decompress a message compressed with filter.compress()
*
- * @param base64 string data
- * @return string message
+ * @name filter.decompress
+ * @function
+ * @param {string} base64 data
+ * @return {string} message
*/
decompress: function(data)
{
@@ -488,12 +547,14 @@ $(function() {
},
/**
- * Compress, then encrypt message with key.
+ * compress, then encrypt message with given key and password
*
- * @param string key
- * @param string password
- * @param string message
- * @return encrypted string data
+ * @name filter.cipher
+ * @function
+ * @param {string} key
+ * @param {string} password
+ * @param {string} message
+ * @return {string} JSON with encrypted data
*/
cipher: function(key, password, message)
{
@@ -507,12 +568,14 @@ $(function() {
},
/**
- * Decrypt message with key, then decompress.
+ * decrypt message with key, then decompress
*
- * @param string key
- * @param string password
- * @param encrypted string data
- * @return string readable message
+ * @name filter.decipher
+ * @function
+ * @param {string} key
+ * @param {string} password
+ * @param {string} JSON with encrypted data
+ * @return {string} decrypted message
*/
decipher: function(key, password, data)
{
@@ -536,27 +599,44 @@ $(function() {
}
};
+ /**
+ * PrivateBin logic
+ *
+ * @name privatebin
+ * @class
+ */
var privatebin = {
/**
* headers to send in AJAX requests
+ *
+ * @name privatebin.headers
+ * @enum {Object}
*/
headers: {'X-Requested-With': 'JSONHttpRequest'},
/**
* URL shortners create address
+ *
+ * @name privatebin.shortenerUrl
+ * @prop {string}
*/
shortenerUrl: '',
/**
* URL of newly created paste
+ *
+ * @name privatebin.createdPasteUrl
+ * @prop {string}
*/
createdPasteUrl: '',
/**
- * Get the current script location (without search or hash part of the URL).
- * eg. http://server.com/zero/?aaaa#bbbb --> http://server.com/zero/
+ * get the current script location (without search or hash part of the URL),
+ * eg. http://example.com/zero/?aaaa#bbbb --> http://example.com/zero/
*
- * @return string current script location
+ * @name privatebin.scriptLocation
+ * @function
+ * @return {string} current script location
*/
scriptLocation: function()
{
@@ -571,10 +651,12 @@ $(function() {
},
/**
- * Get the pastes unique identifier from the URL
- * eg. http://server.com/zero/?c05354954c49a487#c05354954c49a487 returns c05354954c49a487
+ * get the pastes unique identifier from the URL,
+ * eg. http://example.com/zero/?c05354954c49a487#c05354954c49a487 returns c05354954c49a487
*
- * @return string unique identifier
+ * @name privatebin.pasteID
+ * @function
+ * @return {string} unique identifier
*/
pasteID: function()
{
@@ -582,9 +664,11 @@ $(function() {
},
/**
- * Return the deciphering key stored in anchor part of the URL
+ * return the deciphering key stored in anchor part of the URL
*
- * @return string key
+ * @name privatebin.pageKey
+ * @function
+ * @return {string} key
*/
pageKey: function()
{
@@ -618,6 +702,9 @@ $(function() {
/**
* ask the user for the password and set it
+ *
+ * @name privatebin.requestPassword
+ * @function
*/
requestPassword: function()
{
@@ -642,8 +729,10 @@ $(function() {
/**
* use given format on paste, defaults to plain text
*
- * @param string format
- * @param string text
+ * @name privatebin.formatPaste
+ * @function
+ * @param {string} format
+ * @param {string} text
*/
formatPaste: function(format, text)
{
@@ -683,7 +772,7 @@ $(function() {
}
// fall through, as the rest is the same
default:
- // Convert URLs to clickable links.
+ // convert URLs to clickable links
helper.urls2links(this.clearText);
helper.urls2links(this.prettyPrint);
this.clearText.addClass('hidden');
@@ -698,9 +787,11 @@ $(function() {
},
/**
- * Show decrypted text in the display area, including discussion (if open)
+ * show decrypted text in the display area, including discussion (if open)
*
- * @param object paste (optional) object including comments to display (items = array with keys ('data','meta')
+ * @name privatebin.displayMessages
+ * @function
+ * @param {Object} [paste] - (optional) object including comments to display (items = array with keys ('data','meta'))
*/
displayMessages: function(paste)
{
@@ -779,7 +870,7 @@ $(function() {
}
}
- // Display paste expiration / for your eyes only.
+ // display paste expiration / for your eyes only
if (paste.meta.expire_date)
{
var expiration = helper.secondsToHuman(paste.meta.remaining_time),
@@ -809,11 +900,11 @@ $(function() {
));
this.remainingTime.addClass('foryoureyesonly')
.removeClass('hidden');
- // Discourage cloning (as it can't really be prevented).
+ // discourage cloning (as it can't really be prevented)
this.cloneButton.addClass('hidden');
}
- // If the discussion is opened on this paste, display it.
+ // if the discussion is opened on this paste, display it
if (paste.meta.opendiscussion)
{
this.comments.html('');
@@ -824,10 +915,10 @@ $(function() {
var place = this.comments;
var comment = paste.comments[i];
var commenttext = filter.decipher(key, password, comment.data);
- // If parent comment exists, display below (CSS will automatically shift it right.)
+ // if parent comment exists, display below (CSS will automatically shift it to the right)
var cname = '#comment_' + comment.parentid;
- // If the element exists in page
+ // if the element exists in page
if ($(cname).length)
{
place = $(cname);
@@ -838,10 +929,9 @@ $(function() {
+ '');
divComment.find('button').click({commentid: comment.id}, $.proxy(this.openReply, this));
helper.setElementText(divComment.find('div.commentdata'), commenttext);
- // Convert URLs to clickable links in comment.
helper.urls2links(divComment.find('div.commentdata'));
- // Try to get optional nickname:
+ // try to get optional nickname
var nick = filter.decipher(key, password, comment.meta.nickname);
if (nick.length > 0)
{
@@ -855,7 +945,7 @@ $(function() {
.text(' (' + (new Date(comment.meta.postdate * 1000).toLocaleString()) + ')')
.attr('title', 'CommentID: ' + comment.id);
- // If an avatar is available, display it.
+ // if an avatar is available, display it
if (comment.meta.vizhash)
{
divComment.find('span.nickname')
@@ -878,9 +968,11 @@ $(function() {
},
/**
- * Open the comment entry when clicking the "Reply" button of a comment.
+ * open the comment entry when clicking the "Reply" button of a comment
*
- * @param Event event
+ * @name privatebin.openReply
+ * @function
+ * @param {Event} event
*/
openReply: function(event)
{
@@ -889,7 +981,7 @@ $(function() {
commentid = event.data.commentid,
hint = i18n._('Optional nickname...');
- // Remove any other reply area.
+ // remove any other reply area
$('div.reply').remove();
var reply = $(
'
* magnet:?xt.1=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C&xt.2=urn:sha1:TXGCZQTH26NL6OUQAJJPFALHG2LTGBC7
- * http://localhost:8800/zero/?6f09182b8ea51997#WtLEUO5Epj9UHAV9JFs+6pUQZp13TuspAUjnF+iM+dM=
- * http://user:password@localhost:8800/zero/?6f09182b8ea51997#WtLEUO5Epj9UHAV9JFs+6pUQZp13TuspAUjnF+iM+dM=
- *