upgrade to 1.6.5

This commit is contained in:
ilmar 2018-04-24 12:25:56 +03:00
parent d6fa065ef2
commit 7cc7bb1abc
38 changed files with 318 additions and 191 deletions

View File

@ -1,3 +1,24 @@
# 1.6.5
* SECURITY: Escape data when listing available plugins
* FIX: Fix typo in apicalls.js which prevented importing isValidJSONPName
* FIX: fixed plugin dependency issue
* FIX: Update iframe_editor.css
* FIX: unbreak Safari iOS line wrapping
# 1.6.4
* SECURITY: exploitable /admin access - CVE-2018-9845
* SECURITY: DoS with pad exports - CVE-2018-9327
* SECURITY: Remote Code Execution - CVE-2018-9326
* SECURITY: Pad data leak - CVE-2018-9325
* Fix: Admin redirect URL
* Fix: Various script Fixes
* Fix: Various CSS/Style/Layout fixes
* NEW: Improved Pad contents readability
* NEW: Hook: onAccessCheck
* NEW: SESSIONKEY and APIKey customizable path
* NEW: checkPads script
* NEW: Support "cluster mode"
# 1.6.3 # 1.6.3
* SECURITY: Update ejs * SECURITY: Update ejs
* SECURITY: xss vulnerability when reading window.location.href * SECURITY: xss vulnerability when reading window.location.href
@ -56,7 +77,7 @@
* NEW: Allow LibreOffice to be used when exporting a pad * NEW: Allow LibreOffice to be used when exporting a pad
* NEW: Create hook exportHtmlAdditionalTagsWithData * NEW: Create hook exportHtmlAdditionalTagsWithData
* NEW: Improve DB migration performance * NEW: Improve DB migration performance
* NEW: allow settings to be applied from the filesystem * NEW: allow settings to be applied from the filesystem
* NEW: remove applySettings hook and allow credentials.json to be part of core * NEW: remove applySettings hook and allow credentials.json to be part of core
* NEW: Use exec to switch to node process * NEW: Use exec to switch to node process
* NEW: Validate incoming color codes * NEW: Validate incoming color codes
@ -85,7 +106,7 @@
* Fix: switchToPad method * Fix: switchToPad method
* Fix: Dead keys * Fix: Dead keys
* Fix: Preserve new lines in copy-pasted text * Fix: Preserve new lines in copy-pasted text
* Fix: Compatibility mode on IE * Fix: Compatibility mode on IE
* Fix: Content Collector to get the class of the DOM-node * Fix: Content Collector to get the class of the DOM-node
* Fix: Timeslider export links * Fix: Timeslider export links
* Fix: Double prompt on file upload * Fix: Double prompt on file upload
@ -212,7 +233,7 @@
* Fix: Session Deletion error * Fix: Session Deletion error
* Fix: Allow browser tabs to be cycled when focus is in editor * Fix: Allow browser tabs to be cycled when focus is in editor
* Fix: Various Editor issues with Easysync potentially entering forever loop on bad changeset * Fix: Various Editor issues with Easysync potentially entering forever loop on bad changeset
# 1.4 # 1.4
* NEW: Disable toolbar items through settings.json * NEW: Disable toolbar items through settings.json
* NEW: Internal stats/metrics engine * NEW: Internal stats/metrics engine
@ -244,7 +265,7 @@
# 1.3 # 1.3
* NEW: We now follow the semantic versioning scheme! * NEW: We now follow the semantic versioning scheme!
* NEW: Option to disable IP logging * NEW: Option to disable IP logging
* NEW: Localisation updates from http://translatewiki.net. * NEW: Localisation updates from http://translatewiki.net.
* Fix: Fix readOnly group pads * Fix: Fix readOnly group pads
* Fix: don't fetch padList on every request * Fix: don't fetch padList on every request
@ -337,7 +358,7 @@
* NEW: Add authorId to chat and userlist as a data attribute * NEW: Add authorId to chat and userlist as a data attribute
* NEW: Refactor and fix our frontend tests * NEW: Refactor and fix our frontend tests
* NEW: Localisation updates * NEW: Localisation updates
# 1.2.81 # 1.2.81
* Fix: CtrlZ-Y for Undo Redo * Fix: CtrlZ-Y for Undo Redo
@ -377,7 +398,7 @@
* Other: Change loading message asking user to please wait on first build * Other: Change loading message asking user to please wait on first build
* Other: Allow etherpad to use global npm installation (Safe since node 6.3) * Other: Allow etherpad to use global npm installation (Safe since node 6.3)
* Other: Better documentation for log rotation and log message handling * Other: Better documentation for log rotation and log message handling
# 1.2.7 # 1.2.7

View File

@ -1,4 +1,4 @@
# Developer Guidelines # Contributor Guidelines
(Please talk to people on the mailing list before you change this page, see our section on [how to get in touch](https://github.com/ether/etherpad-lite#get-in-touch)) (Please talk to people on the mailing list before you change this page, see our section on [how to get in touch](https://github.com/ether/etherpad-lite#get-in-touch))
## How to write a bug report ## How to write a bug report
@ -35,7 +35,7 @@ The logfile location is defined in startup script or the log is directly shown i
To make sure everybody is going in the same direction: To make sure everybody is going in the same direction:
* easy to install for admins and easy to use for people * easy to install for admins and easy to use for people
* easy to integrate into other apps, but also usable as standalone * easy to integrate into other apps, but also usable as standalone
* using less resources on server side * lightweight and scalable
* extensible, as much functionality should be extendable with plugins so changes don't have to be done in core. * extensible, as much functionality should be extendable with plugins so changes don't have to be done in core.
Also, keep it maintainable. We don't wanna end up as the monster Etherpad was! Also, keep it maintainable. We don't wanna end up as the monster Etherpad was!
@ -92,3 +92,19 @@ You can build the docs e.g. produce html, using `make docs`. At some point in th
## Testing ## Testing
Front-end tests are found in the `tests/frontend/` folder in the repository. Run them by pointing your browser to `<yourdomainhere>/tests/frontend`. Front-end tests are found in the `tests/frontend/` folder in the repository. Run them by pointing your browser to `<yourdomainhere>/tests/frontend`.
## Things you can help with
Etherpad is much more than software. So if you aren't a developer then worry not, there is still a LOT you can do! A big part of what we do is community engagement. You can help in the following ways
* Triage bugs (applying labels) and confirming their existance
* Testing fixes (simply applying them and seeing if it fixes your issue or not) - Some git experience required
* Notifying large site admins of new releases
* Writing Changelogs for releases
* Creating Windows packages
* Creating releases
* Bumping dependencies periodically and checking they don't break anything
* Write proposals for grants
* Co-Author and Publish CVEs
* Work with SFC to maintain legal side of project
* Maintain TODO page - https://github.com/ether/etherpad-lite/wiki/TODO#IMPORTANT_TODOS
* Replying to messages on IRC / The Mailing list / Emails

110
README.md
View File

@ -1,28 +1,43 @@
### This project is looking for a new project lead. If you wish to help steer Etherpad forward please email contact@etherpad.org
[![Deps](https://david-dm.org/ether/etherpad-lite.svg?branch=develop)](https://david-dm.org/ether/etherpad-lite)
[![NSP Status](https://nodesecurity.io/orgs/etherpad/projects/635f6185-35c6-4ed7-931a-0bc62758ece7/badge)](https://nodesecurity.io/orgs/etherpad/projects/635f6185-35c6-4ed7-931a-0bc62758ece7)
# A really-real time collaborative word processor for the web # A really-real time collaborative word processor for the web
![alt text](https://i.imgur.com/zYrGkg3.gif "Etherpad in action on PrimaryPad") ![Demo Etherpad Animated Jif](https://i.imgur.com/zYrGkg3.gif "Etherpad in action on PrimaryPad")
# About # About
Etherpad is a really-real time collaborative editor maintained by the Etherpad Community. Etherpad is a really-real time collaborative editor scalable to thousands of simultanious real time users. Unlike all other collaborative tools Etherpad provides full fidelity data export and portability making it fully GDPR compliant.
Etherpad is written in JavaScript (99.9%) on both the server and client so it's easy for developers to maintain and add new features. Because of this Etherpad has tons of customizations that you can leverage. **[Try it out](http://beta.etherpad.org)**
Etherpad is designed to be easily embeddable and provides a [HTTP API](https://github.com/ether/etherpad-lite/wiki/HTTP-API)
that allows your web application to manage pads, users and groups. It is recommended to use the [available client implementations](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) in order to interact with this API.
There is also a [jQuery plugin](https://github.com/ether/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website.
There's also a full-featured plugin framework, allowing you to easily add your own features. By default your Etherpad is rather sparse and because Etherpad takes a lot of its inspiration from WordPress, plugins are really easy to install and update. Once you have Etherpad installed you should visit the plugin page and take control.
Finally, Etherpad comes with translations into most languages! Users are automatically delivered the correct language for their local settings.
**Visit [beta.etherpad.org](http://beta.etherpad.org) to test it live.**
Also, check out the **[FAQ](https://github.com/ether/etherpad-lite/wiki/FAQ)**, really!
# Installation # Installation
Etherpad works with node v0.10+ (except 6.0 and 6.1). ## Uber-Quick Ubuntu
```
curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
sudo apt-get install -y nodejs
git clone https://github.com/ether/etherpad-lite.git && cd etherpad-lite && bin/run.sh
```
## GNU/Linux and other UNIX-like systems
You'll need gzip, git, curl, libssl develop libraries, python and gcc.
- *For Debian/Ubuntu*: `apt install gzip git curl python libssl-dev pkg-config build-essential`
- *For Fedora/CentOS*: `yum install gzip git curl python openssl-devel && yum groupinstall "Development Tools"`
- *For FreeBSD*: `portinstall node, npm, curl, git (optional)`
Additionally, you'll need [node.js](https://nodejs.org) installed, Ideally the latest stable version, we recommend installing/compiling nodejs from source (avoiding apt).
**As any user (we recommend creating a separate user called etherpad):**
1. Move to a folder where you want to install Etherpad. Clone the git repository `git clone git://github.com/ether/etherpad-lite.git`
2. Change into the new directory containing the cloned source code `cd etherpad-lite`
Now, run `bin/run.sh` and open <http://127.0.0.1:9001> in your browser.
Update to the latest version with `git pull origin`. The next start with bin/run.sh will update the dependencies.
[Next steps](#next-steps).
## Windows ## Windows
@ -52,27 +67,6 @@ If cloning to a subdirectory within another project, you may need to do the foll
2. Edit the db `filename` in `settings.json` to the relative directory with the file (e.g. `application/lib/etherpad-lite/var/dirty.db`) 2. Edit the db `filename` in `settings.json` to the relative directory with the file (e.g. `application/lib/etherpad-lite/var/dirty.db`)
3. Add auto-generated files to the main project `.gitignore` 3. Add auto-generated files to the main project `.gitignore`
[Next steps](#next-steps).
## GNU/Linux and other UNIX-like systems
You'll need gzip, git, curl, libssl develop libraries, python and gcc.
- *For Debian/Ubuntu*: `apt-get install gzip git curl python libssl-dev pkg-config build-essential`
- *For Fedora/CentOS*: `yum install gzip git curl python openssl-devel && yum groupinstall "Development Tools"`
- *For FreeBSD*: `portinstall node, npm, curl, git (optional)`
Additionally, you'll need [node.js](https://nodejs.org) installed, Ideally the latest stable version, we recommend installing/compiling nodejs from source (avoiding apt).
**As any user (we recommend creating a separate user called etherpad):**
1. Move to a folder where you want to install Etherpad. Clone the git repository `git clone git://github.com/ether/etherpad-lite.git`
2. Change into the new directory containing the cloned source code `cd etherpad-lite`
Now, run `bin/run.sh` and open <http://127.0.0.1:9001> in your browser.
Update to the latest version with `git pull origin`. The next start with bin/run.sh will update the dependencies.
You like it? [Next steps](#next-steps).
# Next Steps # Next Steps
## Tweak the settings ## Tweak the settings
@ -85,9 +79,9 @@ You should use a dedicated database such as "mysql", if you are planning on usin
Etherpad is very customizable through plugins. Instructions for installing themes and plugins can be found in [the plugin wiki article](https://github.com/ether/etherpad-lite/wiki/Available-Plugins). Etherpad is very customizable through plugins. Instructions for installing themes and plugins can be found in [the plugin wiki article](https://github.com/ether/etherpad-lite/wiki/Available-Plugins).
## Helpful resources ## Helpful resources
The [wiki](https://github.com/ether/etherpad-lite/wiki) is your one-stop resource for Tutorials and How-to's, really check it out! Also, feel free to improve these wiki pages. The [wiki](https://github.com/ether/etherpad-lite/wiki) is your one-stop resource for Tutorials and How-to's.
Documentation can be found in `docs/`. Documentation can be found in `doc/`.
# Development # Development
@ -100,26 +94,38 @@ You can debug Etherpad using `bin/debugRun.sh`.
If you want to find out how Etherpad's `Easysync` works (the library that makes it really realtime), start with this [PDF](https://github.com/ether/etherpad-lite/raw/master/doc/easysync/easysync-full-description.pdf) (complex, but worth reading). If you want to find out how Etherpad's `Easysync` works (the library that makes it really realtime), start with this [PDF](https://github.com/ether/etherpad-lite/raw/master/doc/easysync/easysync-full-description.pdf) (complex, but worth reading).
## Getting started ## Contributing
You know all this and just want to know how you can help? Read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/blob/master/CONTRIBUTING.md)
Look at the [TODO list](https://github.com/ether/etherpad-lite/wiki/TODO) and our [Issue tracker](https://github.com/ether/etherpad-lite/issues). (Please consider using [jshint](http://www.jshint.com/about/), if you plan to contribute code.)
Also, and most importantly, read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/blob/master/CONTRIBUTING.md), really!
# Get in touch # Get in touch
Join the [mailinglist](https://groups.google.com/group/etherpad-lite-dev) and make some noise on our busy freenode irc channel [#etherpad-lite-dev](https://webchat.freenode.net?channels=#etherpad-lite-dev)! [mailinglist](https://groups.google.com/group/etherpad-lite-dev)
[#etherpad-lite-dev freenode IRC](https://webchat.freenode.net?channels=#etherpad-lite-dev)!
# Modules created for this project # Languages
Etherpad is written in JavaScript on both the server and client so it's easy for developers to maintain and add new features.
* [ueberDB](https://github.com/Pita/ueberDB) "transforms every database into a object key value store" - manages all database access # HTTP API
* [channels](https://github.com/Pita/channels) "Event channels in node.js" - ensures that ueberDB operations are atomic and in series for each key Etherpad is designed to be easily embeddable and provides a [HTTP API](https://github.com/ether/etherpad-lite/wiki/HTTP-API)
* [async-stacktrace](https://github.com/Pita/async-stacktrace) "Improves node.js stacktraces and makes it easier to handle errors" that allows your web application to manage pads, users and groups. It is recommended to use the [available client implementations](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) in order to interact with this API.
# jQuery plugin
There is a [jQuery plugin](https://github.com/ether/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website.
# Plugin Framework
Etherpad offers a plugin framework, allowing you to easily add your own features. By default your Etherpad is extremely light-weight and it's up to you to customize your experience. Once you have Etherpad installed you should visit the plugin page and take control.
# Translations / Localizations (i18n / l10n)
Etherpad comes with translations into all languages thanks to the team at TranslateWiki.
# FAQ
Visit the **[FAQ](https://github.com/ether/etherpad-lite/wiki/FAQ)**.
# Donate! # Donate!
* [Flattr](https://flattr.com/thing/71378/Etherpad-Foundation) * [Flattr](https://flattr.com/thing/71378/Etherpad-Foundation)
* Paypal - Press the donate button on [etherpad.org](http://etherpad.org) * Paypal - Press the donate button on [etherpad.org](http://etherpad.org)
* [Bitcoin](https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a) * [Bitcoin](https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a)
All donations go to the Etherpad foundation which is part of Software Freedom Conservency
# License # License
[Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html) [Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html)

View File

@ -38,4 +38,4 @@ bin/installDeps.sh $* || exit 1
echo "Started Etherpad..." echo "Started Etherpad..."
SCRIPTPATH=`pwd -P` SCRIPTPATH=`pwd -P`
node $SCRIPTPATH/node_modules/ep_etherpad-lite/node/server.js $* node "${$SCRIPTPATH}/node_modules/ep_etherpad-lite/node/server.js" $*

View File

@ -1,4 +1,4 @@
#!/usr/bin/python -u #!/usr/bin/env PYTHONUNBUFFERED=1 python2
# #
# Created by Bjarni R. Einarsson, placed in the public domain. Go wild! # Created by Bjarni R. Einarsson, placed in the public domain. Go wild!
# #

View File

@ -8,7 +8,15 @@ cmd /C node -e "" || ( echo "Please install node.js ( https://nodejs.org )" && e
echo _ echo _
echo Ensure that all dependencies are up to date... If this is the first time you have run Etherpad please be patient. echo Ensure that all dependencies are up to date... If this is the first time you have run Etherpad please be patient.
cmd /C npm install src/ --loglevel warn || exit /B 1
mkdir node_modules
cd /D node_modules
mklink /D "ep_etherpad-lite" "..\src"
cd /D "ep_etherpad-lite"
cmd /C npm install --loglevel warn || exit /B 1
cd /D "%~dp0\.."
echo _ echo _
echo Copying custom templates... echo Copying custom templates...
@ -31,4 +39,4 @@ IF NOT EXIST settings.json (
) )
echo _ echo _
echo Installed Etherpad! To run Etherpad type start.bat echo Installed Etherpad! To run Etherpad type start.bat

View File

@ -108,6 +108,18 @@ Usage examples:
* https://github.com/tiblu/ep_authorship_toggle * https://github.com/tiblu/ep_authorship_toggle
## onAccessCheck
Called from: src/node/db/SecurityManager.js
Things in context:
1. padID - the pad the user wants to access
2. password - the password the user has given to access the pad
3. token - the token of the author
4. sessionCookie - the session the use has
This hook gets called when the access to the concrete pad is being checked. Return `false` to deny access.
## padCreate ## padCreate
Called from: src/node/db/Pad.js Called from: src/node/db/Pad.js

View File

@ -8,7 +8,8 @@
"Quinn", "Quinn",
"Aktron", "Aktron",
"Mormegil", "Mormegil",
"Dvorapa" "Dvorapa",
"Clon"
] ]
}, },
"index.newPad": "Založ nový Pad", "index.newPad": "Založ nový Pad",
@ -63,6 +64,8 @@
"pad.modals.connected": "Připojeno.", "pad.modals.connected": "Připojeno.",
"pad.modals.reconnecting": "Znovupřipojování k Padu…", "pad.modals.reconnecting": "Znovupřipojování k Padu…",
"pad.modals.forcereconnect": "Vynutit znovupřipojení", "pad.modals.forcereconnect": "Vynutit znovupřipojení",
"pad.modals.reconnecttimer": "Zkouším to znovu připojit",
"pad.modals.cancel": "Zrušit",
"pad.modals.userdup": "Otevřeno v jiném okně", "pad.modals.userdup": "Otevřeno v jiném okně",
"pad.modals.userdup.explanation": "Zdá se, že tento Pad je na tomto počítači otevřen ve více než jednom okně.", "pad.modals.userdup.explanation": "Zdá se, že tento Pad je na tomto počítači otevřen ve více než jednom okně.",
"pad.modals.userdup.advice": "Pro použití tohoto okna je třeba se znovu připojit.", "pad.modals.userdup.advice": "Pro použití tohoto okna je třeba se znovu připojit.",

View File

@ -47,7 +47,7 @@
"pad.settings.fontType.monospaced": "Yewca", "pad.settings.fontType.monospaced": "Yewca",
"pad.settings.globalView": "Asayışo Global", "pad.settings.globalView": "Asayışo Global",
"pad.settings.language": "Zıwan:", "pad.settings.language": "Zıwan:",
"pad.importExport.import_export": "Zeredayış/Teberdayış", "pad.importExport.import_export": "Zerredayış/Teberdayış",
"pad.importExport.import": "Dosya ya zi dokumanê meqaleyê de tesadufi bar ke", "pad.importExport.import": "Dosya ya zi dokumanê meqaleyê de tesadufi bar ke",
"pad.importExport.importSuccessful": "Mıwafaq biye", "pad.importExport.importSuccessful": "Mıwafaq biye",
"pad.importExport.export": "Mewcud bloknoti ateberd:", "pad.importExport.export": "Mewcud bloknoti ateberd:",
@ -95,7 +95,7 @@
"timeslider.toolbar.returnbutton": "Peyser şo ped", "timeslider.toolbar.returnbutton": "Peyser şo ped",
"timeslider.toolbar.authors": "Nuştoği:", "timeslider.toolbar.authors": "Nuştoği:",
"timeslider.toolbar.authorsList": "Nuştoği çıniyê", "timeslider.toolbar.authorsList": "Nuştoği çıniyê",
"timeslider.toolbar.exportlink.title": "Teber de", "timeslider.toolbar.exportlink.title": "Teberdayış",
"timeslider.exportCurrent": "Versiyonê enewki teber de:", "timeslider.exportCurrent": "Versiyonê enewki teber de:",
"timeslider.version": "Versiyonê {{version}}", "timeslider.version": "Versiyonê {{version}}",
"timeslider.saved": "{{day}} {{month}}, {{year}} de biyo qeyd", "timeslider.saved": "{{day}} {{month}}, {{year}} de biyo qeyd",

View File

@ -65,7 +65,7 @@
"pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportword": "Microsoft Word",
"pad.importExport.exportpdf": "PDF", "pad.importExport.exportpdf": "PDF",
"pad.importExport.exportopen": "ODF (Open Document Format)", "pad.importExport.exportopen": "ODF (Open Document Format)",
"pad.importExport.abiword.innerHTML": "Tuonti on tuettu vain HTML- ja raakatekstitiedostoista. Lisätietoja tuonnin lisäasetuksista on sivulla <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">install abiword</a>.", "pad.importExport.abiword.innerHTML": "Tuonti on tuettu vain HTML- ja raakatekstitiedostoista. Monipuoliset tuontiominaisuudet ovat käytettävissä <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">asentamalla AbiWord</a>.",
"pad.modals.connected": "Yhdistetty.", "pad.modals.connected": "Yhdistetty.",
"pad.modals.reconnecting": "Muodostetaan yhteyttä muistioon uudelleen...", "pad.modals.reconnecting": "Muodostetaan yhteyttä muistioon uudelleen...",
"pad.modals.forcereconnect": "Pakota yhdistämään uudelleen", "pad.modals.forcereconnect": "Pakota yhdistämään uudelleen",

View File

@ -23,7 +23,8 @@
"Fylip22", "Fylip22",
"C13m3n7", "C13m3n7",
"Wladek92", "Wladek92",
"Urhixidur" "Urhixidur",
"Envlh"
] ]
}, },
"index.newPad": "Nouveau pad", "index.newPad": "Nouveau pad",
@ -48,7 +49,7 @@
"pad.colorpicker.save": "Enregistrer", "pad.colorpicker.save": "Enregistrer",
"pad.colorpicker.cancel": "Annuler", "pad.colorpicker.cancel": "Annuler",
"pad.loading": "Chargement…", "pad.loading": "Chargement…",
"pad.noCookie": "Le témoin (cookie) na pas pu être trouvé. Veuillez autoriser les témoins dans votre navigateur!", "pad.noCookie": "Le cookie na pas pu être trouvé. Veuillez autoriser les cookies dans votre navigateur!",
"pad.passwordRequired": "Vous avez besoin d'un mot de passe pour accéder à ce pad", "pad.passwordRequired": "Vous avez besoin d'un mot de passe pour accéder à ce pad",
"pad.permissionDenied": "Vous n'avez pas la permission daccéder à ce pad", "pad.permissionDenied": "Vous n'avez pas la permission daccéder à ce pad",
"pad.wrongPassword": "Votre mot de passe est incorrect", "pad.wrongPassword": "Votre mot de passe est incorrect",

View File

@ -5,7 +5,8 @@
"Dilyaramude", "Dilyaramude",
"George Animal", "George Animal",
"Gomada", "Gomada",
"Mehk63" "Mehk63",
"Ghybu"
] ]
}, },
"index.newPad": "Bloknota nû", "index.newPad": "Bloknota nû",
@ -40,6 +41,7 @@
"pad.importExport.exportpdf": "PDF", "pad.importExport.exportpdf": "PDF",
"pad.modals.connected": "Hate girêdan.", "pad.modals.connected": "Hate girêdan.",
"pad.modals.reconnecting": "Ji bloknota te re dîsa tê girêdan...", "pad.modals.reconnecting": "Ji bloknota te re dîsa tê girêdan...",
"pad.modals.cancel": "Betal bike",
"pad.modals.userdup": "Di pencereyek din de vebû", "pad.modals.userdup": "Di pencereyek din de vebû",
"pad.modals.userdup.advice": "Ji bo di vê pencereye de bikarbînîy dîsa giredanek çeke.", "pad.modals.userdup.advice": "Ji bo di vê pencereye de bikarbînîy dîsa giredanek çeke.",
"pad.modals.unauth": "Desthilatdar nîne", "pad.modals.unauth": "Desthilatdar nîne",

View File

@ -7,7 +7,8 @@
"Okras", "Okras",
"Volkov", "Volkov",
"Nzeemin", "Nzeemin",
"Facenapalm" "Facenapalm",
"Patrick Star"
] ]
}, },
"index.newPad": "Создать", "index.newPad": "Создать",
@ -58,7 +59,7 @@
"pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportword": "Microsoft Word",
"pad.importExport.exportpdf": "PDF", "pad.importExport.exportpdf": "PDF",
"pad.importExport.exportopen": "ODF (документ OpenOffice)", "pad.importExport.exportopen": "ODF (документ OpenOffice)",
"pad.importExport.abiword.innerHTML": "Вы можете импортировать только из обычного текста или HTML. Для более продвинутых функций импорта, пожалуйста, <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">установите AbiWord</a>.", "pad.importExport.abiword.innerHTML": "Вы можете импортировать только из обычного текста или HTML. Для более продвинутых функций импорта, пожалуйста, <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-with-AbiWord\">установите AbiWord</a>.",
"pad.modals.connected": "Подключен.", "pad.modals.connected": "Подключен.",
"pad.modals.reconnecting": "Повторное подключение к вашему документу", "pad.modals.reconnecting": "Повторное подключение к вашему документу",
"pad.modals.forcereconnect": "Принудительное переподключение", "pad.modals.forcereconnect": "Принудительное переподключение",

View File

@ -11,12 +11,12 @@
}, },
"index.newPad": "కొత్త పలక", "index.newPad": "కొత్త పలక",
"index.createOpenPad": "ఒక పేరుతో పలకని సృష్టించండి లేదా అదే పేరుతో ఉన్న పలకని తెరవండి", "index.createOpenPad": "ఒక పేరుతో పలకని సృష్టించండి లేదా అదే పేరుతో ఉన్న పలకని తెరవండి",
"pad.toolbar.bold.title": "మందం", "pad.toolbar.bold.title": "బొద్దు (Ctrl+B)",
"pad.toolbar.italic.title": "వాలు అక్షరాలు", "pad.toolbar.italic.title": "వాలు (Ctrl+I)",
"pad.toolbar.underline.title": "క్రిందగీత", "pad.toolbar.underline.title": "క్రిందగీత",
"pad.toolbar.strikethrough.title": "కొట్టివేత (Ctrl+5)", "pad.toolbar.strikethrough.title": "కొట్టివేత (Ctrl+5)",
"pad.toolbar.ol.title": "నిర్ధేశింపబడిన జాబితా", "pad.toolbar.ol.title": "క్రమ జాబితా (Ctrl+Shift+N)",
"pad.toolbar.ul.title": "అనిర్దేశిత జాబితా, ( క్రమపద్ధతి లేని జాబితా )", "pad.toolbar.ul.title": "బిందు జాబితా (Ctrl+Shift+L)",
"pad.toolbar.undo.title": "చేయవద్దు", "pad.toolbar.undo.title": "చేయవద్దు",
"pad.toolbar.redo.title": "తిరిగిచెయ్యి", "pad.toolbar.redo.title": "తిరిగిచెయ్యి",
"pad.toolbar.clearAuthorship.title": "మూలకర్తపు వర్ణాలను తీసివేయండి", "pad.toolbar.clearAuthorship.title": "మూలకర్తపు వర్ణాలను తీసివేయండి",
@ -53,6 +53,7 @@
"pad.modals.connected": "సంబంధం కుదిరింది.", "pad.modals.connected": "సంబంధం కుదిరింది.",
"pad.modals.reconnecting": "మీ పలకకు మరల సంబంధం కలుపుతుంది...", "pad.modals.reconnecting": "మీ పలకకు మరల సంబంధం కలుపుతుంది...",
"pad.modals.forcereconnect": "బలవంతంగానైనా సంబంధం కుదిరించు", "pad.modals.forcereconnect": "బలవంతంగానైనా సంబంధం కుదిరించు",
"pad.modals.cancel": "రద్దుచేయి",
"pad.modals.userdup.explanation": "ఈ పలక, ఈ కంప్యూటర్లో ఒకటికన్న ఎక్కువ గవాక్షములలో తెరుచుకున్నట్లు అనిపిస్తుంది.", "pad.modals.userdup.explanation": "ఈ పలక, ఈ కంప్యూటర్లో ఒకటికన్న ఎక్కువ గవాక్షములలో తెరుచుకున్నట్లు అనిపిస్తుంది.",
"pad.modals.userdup.advice": "బదులుగా ఈ గవాక్షమును వాడడానికి మరల సంబంధం కలపండి", "pad.modals.userdup.advice": "బదులుగా ఈ గవాక్షమును వాడడానికి మరల సంబంధం కలపండి",
"pad.modals.unauth": "అధికారం లేదు", "pad.modals.unauth": "అధికారం లేదు",

View File

@ -117,7 +117,7 @@
"timeslider.month.october": "10月", "timeslider.month.october": "10月",
"timeslider.month.november": "11月", "timeslider.month.november": "11月",
"timeslider.month.december": "12月", "timeslider.month.december": "12月",
"timeslider.unnamedauthors": "{{num}}匿名{[plural(num) 作者]}", "timeslider.unnamedauthors": "{{num}}匿名{[plural(num) one:作者, other:作者]}",
"pad.savedrevs.marked": "標記此修訂版本為已儲存修訂版本。", "pad.savedrevs.marked": "標記此修訂版本為已儲存修訂版本。",
"pad.savedrevs.timeslider": "您可使用時段滑標來查看先前保存的版本內容", "pad.savedrevs.timeslider": "您可使用時段滑標來查看先前保存的版本內容",
"pad.userlist.entername": "輸入您的姓名", "pad.userlist.entername": "輸入您的姓名",

View File

@ -25,7 +25,7 @@ var customError = require("../utils/customError");
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString; var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
exports.getColorPalette = function(){ exports.getColorPalette = function(){
return ["#ffc7c7", "#fff1c7", "#e3ffc7", "#c7ffd5", "#c7ffff", "#c7d5ff", "#e3c7ff", "#ffc7f1", "#ff8f8f", "#ffe38f", "#c7ff8f", "#8fffab", "#8fffff", "#8fabff", "#c78fff", "#ff8fe3", "#d97979", "#d9c179", "#a9d979", "#79d991", "#79d9d9", "#7991d9", "#a979d9", "#d979c1", "#d9a9a9", "#d9cda9", "#c1d9a9", "#a9d9b5", "#a9d9d9", "#a9b5d9", "#c1a9d9", "#d9a9cd", "#4c9c82", "#12d1ad", "#2d8e80", "#7485c3", "#a091c7", "#3185ab", "#6818b4", "#e6e76d", "#a42c64", "#f386e5", "#4ecc0c", "#c0c236", "#693224", "#b5de6a", "#9b88fd", "#358f9b", "#496d2f", "#e267fe", "#d23056", "#1a1a64", "#5aa335", "#d722bb", "#86dc6c", "#b5a714", "#955b6a", "#9f2985", "#4b81c8", "#3d6a5b", "#434e16", "#d16084", "#af6a0e", "#8c8bd8"]; return ["#ffc7c7", "#fff1c7", "#e3ffc7", "#c7ffd5", "#c7ffff", "#c7d5ff", "#e3c7ff", "#ffc7f1", "#ffa8a8", "#ffe699", "#cfff9e", "#99ffb3", "#a3ffff", "#99b3ff", "#cc99ff", "#ff99e5", "#e7b1b1", "#e9dcAf", "#cde9af", "#bfedcc", "#b1e7e7", "#c3cdee", "#d2b8ea", "#eec3e6", "#e9cece", "#e7e0ca", "#d3e5c7", "#bce1c5", "#c1e2e2", "#c1c9e2", "#cfc1e2", "#e0bdd9", "#baded3", "#a0f8eb", "#b1e7e0", "#c3c8e4", "#cec5e2", "#b1d5e7", "#cda8f0", "#f0f0a8", "#f2f2a6", "#f5a8eb", "#c5f9a9", "#ececbb", "#e7c4bc", "#daf0b2", "#b0a0fd", "#bce2e7", "#cce2bb", "#ec9afe", "#edabbd", "#aeaeea", "#c4e7b1", "#d722bb", "#f3a5e7", "#ffa8a8", "#d8c0c5", "#eaaedd", "#adc6eb", "#bedad1", "#dee9af", "#e9afc2", "#f8d2a0", "#b3b3e6"];
}; };
/** /**
@ -42,9 +42,9 @@ exports.doesAuthorExists = function (authorID, callback)
} }
/** /**
* Returns the AuthorID for a token. * Returns the AuthorID for a token.
* @param {String} token The token * @param {String} token The token
* @param {Function} callback callback (err, author) * @param {Function} callback callback (err, author)
*/ */
exports.getAuthor4Token = function (token, callback) exports.getAuthor4Token = function (token, callback)
{ {
@ -57,21 +57,21 @@ exports.getAuthor4Token = function (token, callback)
} }
/** /**
* Returns the AuthorID for a mapper. * Returns the AuthorID for a mapper.
* @param {String} token The mapper * @param {String} token The mapper
* @param {String} name The name of the author (optional) * @param {String} name The name of the author (optional)
* @param {Function} callback callback (err, author) * @param {Function} callback callback (err, author)
*/ */
exports.createAuthorIfNotExistsFor = function (authorMapper, name, callback) exports.createAuthorIfNotExistsFor = function (authorMapper, name, callback)
{ {
mapAuthorWithDBKey("mapper2author", authorMapper, function(err, author) mapAuthorWithDBKey("mapper2author", authorMapper, function(err, author)
{ {
if(ERR(err, callback)) return; if(ERR(err, callback)) return;
//set the name of this author //set the name of this author
if(name) if(name)
exports.setAuthorName(author.authorID, name); exports.setAuthorName(author.authorID, name);
//return the authorID //return the authorID
callback(null, author); callback(null, author);
}); });
@ -80,27 +80,27 @@ exports.createAuthorIfNotExistsFor = function (authorMapper, name, callback)
/** /**
* Returns the AuthorID for a mapper. We can map using a mapperkey, * Returns the AuthorID for a mapper. We can map using a mapperkey,
* so far this is token2author and mapper2author * so far this is token2author and mapper2author
* @param {String} mapperkey The database key name for this mapper * @param {String} mapperkey The database key name for this mapper
* @param {String} mapper The mapper * @param {String} mapper The mapper
* @param {Function} callback callback (err, author) * @param {Function} callback callback (err, author)
*/ */
function mapAuthorWithDBKey (mapperkey, mapper, callback) function mapAuthorWithDBKey (mapperkey, mapper, callback)
{ {
//try to map to an author //try to map to an author
db.get(mapperkey + ":" + mapper, function (err, author) db.get(mapperkey + ":" + mapper, function (err, author)
{ {
if(ERR(err, callback)) return; if(ERR(err, callback)) return;
//there is no author with this mapper, so create one //there is no author with this mapper, so create one
if(author == null) if(author == null)
{ {
exports.createAuthor(null, function(err, author) exports.createAuthor(null, function(err, author)
{ {
if(ERR(err, callback)) return; if(ERR(err, callback)) return;
//create the token2author relation //create the token2author relation
db.set(mapperkey + ":" + mapper, author.authorID); db.set(mapperkey + ":" + mapper, author.authorID);
//return the author //return the author
callback(null, author); callback(null, author);
}); });
@ -110,7 +110,7 @@ function mapAuthorWithDBKey (mapperkey, mapper, callback)
{ {
//update the timestamp of this author //update the timestamp of this author
db.setSub("globalAuthor:" + author, ["timestamp"], new Date().getTime()); db.setSub("globalAuthor:" + author, ["timestamp"], new Date().getTime());
//return the author //return the author
callback(null, {authorID: author}); callback(null, {authorID: author});
} }
@ -118,20 +118,20 @@ function mapAuthorWithDBKey (mapperkey, mapper, callback)
} }
/** /**
* Internal function that creates the database entry for an author * Internal function that creates the database entry for an author
* @param {String} name The name of the author * @param {String} name The name of the author
*/ */
exports.createAuthor = function(name, callback) exports.createAuthor = function(name, callback)
{ {
//create the new author name //create the new author name
var author = "a." + randomString(16); var author = "a." + randomString(16);
//create the globalAuthors db entry //create the globalAuthors db entry
var authorObj = {"colorId" : Math.floor(Math.random()*(exports.getColorPalette().length)), "name": name, "timestamp": new Date().getTime()}; var authorObj = {"colorId" : Math.floor(Math.random()*(exports.getColorPalette().length)), "name": name, "timestamp": new Date().getTime()};
//set the global author db entry //set the global author db entry
db.set("globalAuthor:" + author, authorObj); db.set("globalAuthor:" + author, authorObj);
callback(null, {authorID: author}); callback(null, {authorID: author});
} }
@ -212,7 +212,7 @@ exports.listPadsOfAuthor = function (authorID, callback)
} }
//everything is fine, return the pad IDs //everything is fine, return the pad IDs
else else
{ {
var pads = []; var pads = [];
if(author.padIDs != null) if(author.padIDs != null)
{ {
@ -238,16 +238,16 @@ exports.addPad = function (authorID, padID)
{ {
if(ERR(err)) return; if(ERR(err)) return;
if(author == null) return; if(author == null) return;
//the entry doesn't exist so far, let's create it //the entry doesn't exist so far, let's create it
if(author.padIDs == null) if(author.padIDs == null)
{ {
author.padIDs = {}; author.padIDs = {};
} }
//add the entry for this pad //add the entry for this pad
author.padIDs[padID] = 1;// anything, because value is not used author.padIDs[padID] = 1;// anything, because value is not used
//save the new element back //save the new element back
db.set("globalAuthor:" + authorID, author); db.set("globalAuthor:" + authorID, author);
}); });
@ -264,11 +264,11 @@ exports.removePad = function (authorID, padID)
{ {
if(ERR(err)) return; if(ERR(err)) return;
if(author == null) return; if(author == null) return;
if(author.padIDs != null) if(author.padIDs != null)
{ {
//remove pad from author //remove pad from author
delete author.padIDs[padID]; delete author.padIDs[padID];
db.set("globalAuthor:" + authorID, author); db.set("globalAuthor:" + authorID, author);
} }
}); });

View File

@ -464,9 +464,10 @@ Pad.prototype.copy = function copy(destinationID, force, callback) {
} }
else force = true; else force = true;
//kick everyone from this pad // Kick everyone from this pad.
// TODO: this presents a message on the client saying that the pad was 'deleted'. Fix this? // This was commented due to https://github.com/ether/etherpad-lite/issues/3183.
padMessageHandler.kickSessionsFromPad(sourceID); // Do we really need to kick everyone out?
// padMessageHandler.kickSessionsFromPad(sourceID);
// flush the source pad: // flush the source pad:
_this.saveToDatabase(); _this.saveToDatabase();

View File

@ -22,6 +22,7 @@
var ERR = require("async-stacktrace"); var ERR = require("async-stacktrace");
var async = require("async"); var async = require("async");
var authorManager = require("./AuthorManager"); var authorManager = require("./AuthorManager");
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks.js");
var padManager = require("./PadManager"); var padManager = require("./PadManager");
var sessionManager = require("./SessionManager"); var sessionManager = require("./SessionManager");
var settings = require("../utils/Settings"); var settings = require("../utils/Settings");
@ -45,6 +46,14 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
return; return;
} }
// allow plugins to deny access
var deniedByHook = hooks.callAll("onAccessCheck", {'padID': padID, 'password': password, 'token': token, 'sessionCookie': sessionCookie}).indexOf(false) > -1;
if(deniedByHook)
{
callback(null, {accessStatus: "deny"});
return;
}
// a valid session is required (api-only mode) // a valid session is required (api-only mode)
if(settings.requireSession) if(settings.requireSession)
{ {

View File

@ -24,17 +24,19 @@ var fs = require("fs");
var api = require("../db/API"); var api = require("../db/API");
var padManager = require("../db/PadManager"); var padManager = require("../db/PadManager");
var randomString = require("../utils/randomstring"); var randomString = require("../utils/randomstring");
var argv = require('../utils/Cli').argv;
//ensure we have an apikey //ensure we have an apikey
var apikey = null; var apikey = null;
var apikeyFilename = argv.apikey || "./APIKEY.txt";
try try
{ {
apikey = fs.readFileSync("./APIKEY.txt","utf8"); apikey = fs.readFileSync(apikeyFilename,"utf8");
} }
catch(e) catch(e)
{ {
apikey = randomString(32); apikey = randomString(32);
fs.writeFileSync("./APIKEY.txt",apikey,"utf8"); fs.writeFileSync(apikeyFilename,apikey,"utf8");
} }
//a list of all functions //a list of all functions

View File

@ -90,7 +90,7 @@ exports.doImport = function(req, res, padId)
//this allows us to accept source code files like .c or .java //this allows us to accept source code files like .c or .java
function(callback) { function(callback) {
var fileEnding = path.extname(srcFile).toLowerCase() var fileEnding = path.extname(srcFile).toLowerCase()
, knownFileEndings = [".txt", ".doc", ".docx", ".pdf", ".odt", ".html", ".htm", ".etherpad"] , knownFileEndings = [".txt", ".doc", ".docx", ".pdf", ".odt", ".html", ".htm", ".etherpad", ".rtf"]
, fileEndingKnown = (knownFileEndings.indexOf(fileEnding) > -1); , fileEndingKnown = (knownFileEndings.indexOf(fileEnding) > -1);
//if the file ending is known, continue as normal //if the file ending is known, continue as normal

View File

@ -25,6 +25,10 @@ exports.createServer = function () {
else{ else{
console.warn("Admin username and password not set in settings.json. To access admin please uncomment and edit 'users' in settings.json"); console.warn("Admin username and password not set in settings.json. To access admin please uncomment and edit 'users' in settings.json");
} }
var env = process.env.NODE_ENV || 'development';
if(env !== 'production'){
console.warn("Etherpad is running in Development mode. This mode is slower for users and less secure than production mode. You should set the NODE_ENV environment variable to production by using: export NODE_ENV=production");
}
} }
exports.restartServer = function () { exports.restartServer = function () {

View File

@ -2,7 +2,7 @@ var eejs = require('ep_etherpad-lite/node/eejs');
exports.expressCreateServer = function (hook_name, args, cb) { exports.expressCreateServer = function (hook_name, args, cb) {
args.app.get('/admin', function(req, res) { args.app.get('/admin', function(req, res) {
if('/' != req.path[req.path.length-1]) return res.redirect('/admin/'); if('/' != req.path[req.path.length-1]) return res.redirect('./admin/');
res.send( eejs.require("ep_etherpad-lite/templates/admin/index.html", {}) ); res.send( eejs.require("ep_etherpad-lite/templates/admin/index.html", {}) );
}); });
} }

View File

@ -3,7 +3,7 @@ var apiLogger = log4js.getLogger("API");
var clientLogger = log4js.getLogger("client"); var clientLogger = log4js.getLogger("client");
var formidable = require('formidable'); var formidable = require('formidable');
var apiHandler = require('../../handler/APIHandler'); var apiHandler = require('../../handler/APIHandler');
var isVarName = require('is-var-name'); var isValidJSONPName = require('./isValidJSONPName');
//This is for making an api call, collecting all post information and passing it to the apiHandler //This is for making an api call, collecting all post information and passing it to the apiHandler
var apiCaller = function(req, res, fields) { var apiCaller = function(req, res, fields) {
@ -19,7 +19,7 @@ var apiCaller = function(req, res, fields) {
apiLogger.info("RESPONSE, " + req.params.func + ", " + response); apiLogger.info("RESPONSE, " + req.params.func + ", " + response);
//is this a jsonp call, if yes, add the function call //is this a jsonp call, if yes, add the function call
if(req.query.jsonp && isVarName(response)) if(req.query.jsonp && isValidJSONPName.check(req.query.jsonp))
response = req.query.jsonp + "(" + response + ")"; response = req.query.jsonp + "(" + response + ")";
res._____send(response); res._____send(response);
@ -46,7 +46,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//The Etherpad client side sends information about how a disconnect happened //The Etherpad client side sends information about how a disconnect happened
args.app.post('/ep/pad/connection-diagnostic-info', function(req, res) { args.app.post('/ep/pad/connection-diagnostic-info', function(req, res) {
new formidable.IncomingForm().parse(req, function(err, fields, files) { new formidable.IncomingForm().parse(req, function(err, fields, files) {
clientLogger.info("DIAGNOSTIC-INFO: " + fields.diagnosticInfo); clientLogger.info("DIAGNOSTIC-INFO: " + fields.diagnosticInfo);
res.end("OK"); res.end("OK");
}); });
@ -54,7 +54,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//The Etherpad client side sends information about client side javscript errors //The Etherpad client side sends information about client side javscript errors
args.app.post('/jserror', function(req, res) { args.app.post('/jserror', function(req, res) {
new formidable.IncomingForm().parse(req, function(err, fields, files) { new formidable.IncomingForm().parse(req, function(err, fields, files) {
try { try {
var data = JSON.parse(fields.errorInfo) var data = JSON.parse(fields.errorInfo)
}catch(e){ }catch(e){
@ -64,7 +64,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
res.end("OK"); res.end("OK");
}); });
}); });
//Provide a possibility to query the latest available API version //Provide a possibility to query the latest available API version
args.app.get('/api', function (req, res) { args.app.get('/api', function (req, res) {
res.json({"currentVersion" : apiHandler.latestApiVersion}); res.json({"currentVersion" : apiHandler.latestApiVersion});

View File

@ -2,6 +2,7 @@ var hasPadAccess = require("../../padaccess");
var settings = require('../../utils/Settings'); var settings = require('../../utils/Settings');
var exportHandler = require('../../handler/ExportHandler'); var exportHandler = require('../../handler/ExportHandler');
var importHandler = require('../../handler/ImportHandler'); var importHandler = require('../../handler/ImportHandler');
var padManager = require("../../db/PadManager");
exports.expressCreateServer = function (hook_name, args, cb) { exports.expressCreateServer = function (hook_name, args, cb) {
args.app.get('/p/:pad/:rev?/export/:type', function(req, res, next) { args.app.get('/p/:pad/:rev?/export/:type', function(req, res, next) {
@ -22,14 +23,29 @@ exports.expressCreateServer = function (hook_name, args, cb) {
res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Origin", "*");
hasPadAccess(req, res, function() { hasPadAccess(req, res, function() {
exportHandler.doExport(req, res, req.params.pad, req.params.type); console.log('req.params.pad', req.params.pad);
padManager.doesPadExists(req.params.pad, function(err, exists)
{
if(!exists) {
return next();
}
exportHandler.doExport(req, res, req.params.pad, req.params.type);
});
}); });
}); });
//handle import requests //handle import requests
args.app.post('/p/:pad/import', function(req, res, next) { args.app.post('/p/:pad/import', function(req, res, next) {
hasPadAccess(req, res, function() { hasPadAccess(req, res, function() {
importHandler.doImport(req, res, req.params.pad); padManager.doesPadExists(req.params.pad, function(err, exists)
{
if(!exists) {
return next();
}
importHandler.doImport(req, res, req.params.pad);
});
}); });
}); });
} }

View File

@ -20,7 +20,7 @@ exports.basicAuth = function (req, res, next) {
// Do not require auth for static paths and the API...this could be a bit brittle // Do not require auth for static paths and the API...this could be a bit brittle
if (req.path.match(/^\/(static|javascripts|pluginfw|api)/)) return cb(true); if (req.path.match(/^\/(static|javascripts|pluginfw|api)/)) return cb(true);
if (req.path.indexOf('/admin') != 0) { if (req.path.toLowerCase().indexOf('/admin') != 0) {
if (!settings.requireAuthentication) return cb(true); if (!settings.requireAuthentication) return cb(true);
if (!settings.requireAuthorization && req.session && req.session.user) return cb(true); if (!settings.requireAuthorization && req.session && req.session.user) return cb(true);
} }
@ -36,13 +36,16 @@ exports.basicAuth = function (req, res, next) {
var userpass = new Buffer(req.headers.authorization.split(' ')[1], 'base64').toString().split(":") var userpass = new Buffer(req.headers.authorization.split(' ')[1], 'base64').toString().split(":")
var username = userpass.shift(); var username = userpass.shift();
var password = userpass.join(':'); var password = userpass.join(':');
var fallback = function(success) {
if (settings.users[username] != undefined && settings.users[username].password == password) { if (success) return cb(true);
settings.users[username].username = username; if (settings.users[username] != undefined && settings.users[username].password === password) {
req.session.user = settings.users[username]; settings.users[username].username = username;
return cb(true); req.session.user = settings.users[username];
} return cb(true);
return hooks.aCallFirst("authenticate", {req: req, res:res, next:next, username: username, password: password}, hookResultMangle(cb)); }
return cb(false);
};
return hooks.aCallFirst("authenticate", {req: req, res:res, next:next, username: username, password: password}, hookResultMangle(fallback));
} }
hooks.aCallFirst("authenticate", {req: req, res:res, next:next}, hookResultMangle(cb)); hooks.aCallFirst("authenticate", {req: req, res:res, next:next}, hookResultMangle(cb));
} }
@ -126,4 +129,3 @@ exports.expressConfigure = function (hook_name, args, cb) {
args.app.use(exports.basicAuth); args.app.use(exports.basicAuth);
} }

View File

@ -39,5 +39,15 @@ for ( var i = 0; i < argv.length; i++ ) {
exports.argv.credentials = arg; exports.argv.credentials = arg;
} }
// Override location of settings.json file
if ( prevArg == '--sessionkey' || prevArg == '-k' ) {
exports.argv.sessionkey = arg;
}
// Override location of settings.json file
if ( prevArg == '--apikey' || prevArg == '-k' ) {
exports.argv.apikey = arg;
}
prevArg = arg; prevArg = arg;
} }

View File

@ -22,25 +22,18 @@ var ERR = require("async-stacktrace");
exports.getPadRaw = function(padId, callback){ exports.getPadRaw = function(padId, callback){
async.waterfall([ async.waterfall([
function(cb){ function(cb){
db.get("pad:"+padId, cb);
// Get the Pad
db.findKeys("pad:"+padId, null, function(err,padcontent){
if(!err){
cb(err, padcontent);
}
})
}, },
function(padcontent,cb){ function(padcontent,cb){
var records = ["pad:"+padId];
for (var i = 0; i <= padcontent.head; i++) {
records.push("pad:"+padId+":revs:" + i);
}
for (var i = 0; i <= padcontent.chatHead; i++) {
records.push("pad:"+padId+":chat:" + i);
}
// Get the Pad available content keys
db.findKeys("pad:"+padId+":*", null, function(err,records){
if(!err){
for (var key in padcontent) { records.push(padcontent[key]);}
cb(err, records);
}
})
},
function(records, cb){
var data = {}; var data = {};
async.forEachSeries(Object.keys(records), function(key, r){ async.forEachSeries(Object.keys(records), function(key, r){
@ -69,7 +62,7 @@ exports.getPadRaw = function(padId, callback){
} }
r(null); // callback; r(null); // callback;
}); });
}, function(err){ }, function(err){
cb(err, data); cb(err, data);
}) })
} }

View File

@ -110,31 +110,27 @@ function getHTMLFromAtext(pad, atext, authorColors)
css+="<style>\n"; css+="<style>\n";
for (var a in apool.numToAttrib) { for (var a in apool.numToAttrib) {
if (apool.numToAttrib.hasOwnProperty.call(a)) { var attr = apool.numToAttrib[a];
var attr = apool.numToAttrib[a];
var newLength = null; //skip non author attributes
var propName = null; if(attr[0] === "author" && attr[1] !== ""){
//skip non author attributes //add to props array
if (attr[0] === "author" && attr[1] !== ""){ var propName = "author" + stripDotFromAuthorID(attr[1]);
//add to props array var newLength = props.push(propName);
propName = "author" + stripDotFromAuthorID(attr[1]); anumMap[a] = newLength -1;
newLength = props.push(propName);
anumMap[a] = newLength - 1;
css+="." + propName + " {background-color: " + authorColors[attr[1]]+ "}\n"; css+="." + propName + " {background-color: " + authorColors[attr[1]]+ "}\n";
} else if(attr[0] === "removed") { } else if(attr[0] === "removed") {
propName = "removed"; var propName = "removed";
newLength = props.push(propName); var newLength = props.push(propName);
anumMap[a] = newLength -1; anumMap[a] = newLength -1;
css+=".removed {text-decoration: line-through; " + css+=".removed {text-decoration: line-through; " +
"-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)'; "+ "-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)'; "+
"filter: alpha(opacity=80); "+ "filter: alpha(opacity=80); "+
"opacity: 0.8; "+ "opacity: 0.8; "+
"}\n"; "}\n";
}
} }
} }

View File

@ -35,7 +35,21 @@ var queue = async.queue(doConvertTask, 1);
* @param {Function} callback Standard callback function * @param {Function} callback Standard callback function
*/ */
exports.convertFile = function(srcFile, destFile, type, callback) { exports.convertFile = function(srcFile, destFile, type, callback) {
queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback}); // soffice can't convert from html to doc directly (verified with LO 5 and 6)
// we need to convert to odt first, then to doc
// to avoid `Error: no export filter for /tmp/xxxx.doc` error
if (type === 'doc') {
queue.push({
"srcFile": srcFile,
"destFile": destFile.replace(/\.doc$/, '.odt'),
"type": 'odt',
"callback": function () {
queue.push({"srcFile": srcFile.replace(/\.html$/, '.odt'), "destFile": destFile, "type": type, "callback": callback});
}
});
} else {
queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback});
}
}; };
function doConvertTask(task, callback) { function doConvertTask(task, callback) {

View File

@ -476,11 +476,12 @@ exports.reloadSettings = function reloadSettings() {
} }
if (!exports.sessionKey) { if (!exports.sessionKey) {
var sessionkeyFilename = argv.sessionkey || "./SESSIONKEY.txt";
try { try {
exports.sessionKey = fs.readFileSync("./SESSIONKEY.txt","utf8"); exports.sessionKey = fs.readFileSync(sessionkeyFilename,"utf8");
} catch(e) { } catch(e) {
exports.sessionKey = randomString(32); exports.sessionKey = randomString(32);
fs.writeFileSync("./SESSIONKEY.txt",exports.sessionKey,"utf8"); fs.writeFileSync(sessionkeyFilename,exports.sessionKey,"utf8");
} }
} else { } else {
console.warn("Declaring the sessionKey in the settings.json is deprecated. This value is auto-generated now. Please remove the setting from the file."); console.warn("Declaring the sessionKey in the settings.json is deprecated. This value is auto-generated now. Please remove the setting from the file.");

View File

@ -17,18 +17,18 @@
"etherpad-require-kernel" : "1.0.9", "etherpad-require-kernel" : "1.0.9",
"resolve" : "1.1.7", "resolve" : "1.1.7",
"socket.io" : "1.7.3", "socket.io" : "1.7.3",
"ueberdb2" : "0.3.7", "ueberdb2" : "0.3.8",
"express" : "4.13.4", "express" : "4.13.4",
"express-session" : "1.13.0", "express-session" : "1.13.0",
"cookie-parser" : "1.3.4", "cookie-parser" : "1.3.4",
"async" : "0.9.0", "async" : "0.9.0",
"clean-css" : "3.4.19", "clean-css" : "3.4.19",
"uglify-js" : "2.6.2", "uglify-js" : "2.6.2",
"formidable" : "1.0.17", "formidable" : "1.2.1",
"log4js" : "0.6.35", "log4js" : "0.6.35",
"cheerio" : "0.20.0", "cheerio" : "0.20.0",
"async-stacktrace" : "0.0.2", "async-stacktrace" : "0.0.2",
"npm" : "4.0.2", "npm" : ">=4.0.2",
"ejs" : "2.5.7", "ejs" : "2.5.7",
"graceful-fs" : "4.1.3", "graceful-fs" : "4.1.3",
"slide" : "1.1.6", "slide" : "1.1.6",
@ -42,13 +42,12 @@
"channels" : "0.0.4", "channels" : "0.0.4",
"jsonminify" : "0.4.1", "jsonminify" : "0.4.1",
"measured" : "1.1.0", "measured" : "1.1.0",
"mocha" : "2.4.5", "mocha" : "5.0.5",
"supertest" : "1.2.0", "supertest" : "3.0.0"
"is-var-name" : "1.0.0" },
},
"bin": { "etherpad-lite": "./node/server.js" }, "bin": { "etherpad-lite": "./node/server.js" },
"devDependencies": { "devDependencies": {
"wd" : "0.3.11" "wd" : "1.6.1"
}, },
"engines" : { "node" : ">=0.10.0", "engines" : { "node" : ">=0.10.0",
"npm" : ">=1.0" "npm" : ">=1.0"
@ -56,6 +55,6 @@
"repository" : { "type" : "git", "repository" : { "type" : "git",
"url" : "http://github.com/ether/etherpad-lite.git" "url" : "http://github.com/ether/etherpad-lite.git"
}, },
"version" : "1.6.3", "version" : "1.6.5",
"license" : "Apache-2.0" "license" : "Apache-2.0"
} }

View File

@ -31,13 +31,17 @@ body {
body.grayedout { background-color: #eee !important } body.grayedout { background-color: #eee !important }
#innerdocbody { #innerdocbody {
font-size: 12px; /* overridden by body.style */ font-size: 16px; /* overridden by body.style */
font-family:Arial, sans-serif; /* overridden by body.style */ font-family:Arial, sans-serif; /* overridden by body.style */
line-height: 16px; /* overridden by body.style */ line-height: 22px; /* overridden by body.style */
background-color: white; background-color: white;
color: black; color: black;
} }
.innerdocbody>div{
padding: 1px;
}
body.doesWrap { body.doesWrap {
/* white-space: pre-wrap; */ /* white-space: pre-wrap; */

View File

@ -3,8 +3,9 @@ html,
body, body,
p { p {
margin: 0; margin: 0;
padding: 0; padding: 0px;
} }
.clear { .clear {
clear: both clear: both
} }
@ -1071,9 +1072,9 @@ input[type=checkbox] {
overflow: auto; overflow: auto;
} }
#mycolorpicker { #mycolorpicker {
left: -73px; left: 0px;
top:auto !important; top:37px !important;
bottom:33px !important; position:fixed;
/* #mycolorpicker: width -#users: width */; /* #mycolorpicker: width -#users: width */;
} }
#editorcontainer { #editorcontainer {

View File

@ -5404,8 +5404,8 @@ function Ace2Inner(){
// height is taken to be the top offset of the next line. If we // height is taken to be the top offset of the next line. If we
// didn't do this special case, we would miss out on any top margin // didn't do this special case, we would miss out on any top margin
// included on the first line. The default stylesheet doesn't add // included on the first line. The default stylesheet doesn't add
// extra margins, but plugins might. // extra margins/padding, but plugins might.
h = b.nextSibling.offsetTop; h = b.nextSibling.offsetTop - window.getComputedStyle(doc.body).getPropertyValue("padding-top");
} else { } else {
h = b.nextSibling.offsetTop - b.offsetTop; h = b.nextSibling.offsetTop - b.offsetTop;
} }

View File

@ -79,12 +79,17 @@ $(document).ready(function () {
for (attr in plugin) { for (attr in plugin) {
if(attr == "name"){ // Hack to rewrite URLS into name if(attr == "name"){ // Hack to rewrite URLS into name
row.find(".name").html("<a target='_blank' title='Plugin details' href='https://npmjs.org/package/"+plugin['name']+"'>"+plugin['name'].substr(3)+"</a>"); // remove 'ep_' var link = $('<a>');
}else{ link.attr('href', 'https://npmjs.org/package/'+plugin['name']);
link.attr('plugin', 'Plugin details');
link.attr('target', '_blank');
link.text(plugin['name'].substr(3));
row.find('.name').append(link);
} else {
row.find("." + attr).text(plugin[attr]); row.find("." + attr).text(plugin[attr]);
} }
} }
row.find(".version").html( plugin.version ); row.find(".version").text(plugin.version);
row.addClass(plugin.name) row.addClass(plugin.name)
row.data('plugin', plugin.name) row.data('plugin', plugin.name)
container.append(row); container.append(row);

View File

@ -33,7 +33,7 @@ var padcookie = (function()
return null; return null;
} }
// look for (start of string OR semicolon) followed by whitespace followed by prefs=(something); // look for (start of string OR semicolon) followed by whitespace followed by prefs=(something);
var regexResult = document.cookie.match(new RegExp("(?:^|;)\s*" + cookieName + "=([^;]*)(?:;|$)")); var regexResult = document.cookie.match(new RegExp("(?:^|;)\\s*" + cookieName + "=([^;]*)(?:;|$)"));
if ((!regexResult) || (!regexResult[1])) if ((!regexResult) || (!regexResult[1]))
{ {
return null; return null;

View File

@ -124,7 +124,7 @@ exports.getPackages = function (cb) {
var tmp = {}; var tmp = {};
tmp[data.name] = data; tmp[data.name] = data;
flatten(tmp[undefined].dependencies); flatten(tmp[data.name].dependencies);
cb(null, packages); cb(null, packages);
}); });
}; };

View File

@ -139,6 +139,5 @@ ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol > ol {
</head> </head>
<body> <body>
<%- body %> <%- body %>
<div style="display:none"><a href="/javascript" data-jslicense="1">JavaScript license information</a></div>
</body> </body>
</html> </html>