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

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...

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"];
}; };
/** /**

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);

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){

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>