Full Code of jcoppieters/cody for AI

master 0e10677068a2 cached
319 files
3.1 MB
832.7k tokens
915 symbols
1 requests
Download .txt
Showing preview only (3,331K chars total). Download the full file or copy to clipboard to get everything.
Repository: jcoppieters/cody
Branch: master
Commit: 0e10677068a2
Files: 319
Total size: 3.1 MB

Directory structure:
gitextract_3aeu67e9/

├── .gitignore
├── .npmignore
├── Contributing.md
├── History.md
├── LICENSE.md
├── README.md
├── apps/
│   ├── Application.js
│   ├── Dynamic.js
│   └── Static.js
├── bin/
│   ├── create_site.js
│   └── remove_site
├── controllers/
│   ├── ContactController.js
│   ├── Controller.js
│   ├── DashboardController.js
│   ├── EmailController.js
│   ├── FileController.js
│   ├── FormController.js
│   ├── FormDataController.js
│   ├── ImageController.js
│   ├── LoginController.js
│   ├── PageController.js
│   ├── StylesController.js
│   ├── SystemController.js
│   ├── TemplateController.js
│   ├── TreeController.js
│   └── UserController.js
├── doc/
│   ├── Context.txt
│   ├── empty/
│   │   ├── controllers/
│   │   │   └── YourController.js
│   │   ├── empty.sql
│   │   ├── index.js
│   │   ├── locales/
│   │   │   ├── en.json
│   │   │   └── zh-CN.json
│   │   ├── static/
│   │   │   ├── css/
│   │   │   │   └── front.css
│   │   │   └── js/
│   │   │       └── script.js
│   │   └── views/
│   │       ├── content.ejs
│   │       ├── footer.ejs
│   │       ├── header.ejs
│   │       ├── index.ejs
│   │       ├── intros.ejs
│   │       ├── menu-left.ejs
│   │       ├── menu-top.ejs
│   │       └── page.ejs
│   ├── hosting_sqlbased/
│   │   ├── codymaster.sql
│   │   └── index.js
│   └── todo.txt
├── index.js
├── makeWebApp.js
├── models/
│   ├── Atom.js
│   ├── Content.js
│   ├── Context.js
│   ├── Item.js
│   ├── Meta.js
│   ├── Model.js
│   ├── Page.js
│   ├── Path.js
│   ├── Template.js
│   ├── User.js
│   └── Website.js
├── package.json
├── startWebApp.js
├── startserver.js
├── static/
│   ├── css/
│   │   ├── cody.css
│   │   └── ui-lightness/
│   │       └── jquery-ui-1.10.1.css
│   └── js/
│       ├── atom-tree.js
│       ├── lib/
│       │   ├── html5shiv.js
│       │   ├── jquery-1.9.1.js
│       │   ├── jquery-ui-1.10.1.js
│       │   ├── jquery.jstree.js
│       │   ├── jquery.validate.js
│       │   ├── localization/
│       │   │   ├── jquery.ui.datepicker-de.js
│       │   │   ├── jquery.ui.datepicker-en.js
│       │   │   ├── jquery.ui.datepicker-es.js
│       │   │   ├── jquery.ui.datepicker-fr.js
│       │   │   ├── jquery.ui.datepicker-nl.js
│       │   │   ├── messages_de.js
│       │   │   ├── messages_en.js
│       │   │   ├── messages_es.js
│       │   │   ├── messages_fr.js
│       │   │   └── messages_nl.js
│       │   └── themes/
│       │       ├── apple/
│       │       │   └── style.css
│       │       ├── classic/
│       │       │   └── style.css
│       │       └── default/
│       │           └── style.css
│       ├── pages-editor.js
│       ├── script.js
│       └── tinymce/
│           ├── jquery.tinymce.js
│           ├── langs/
│           │   └── en.js
│           ├── license.txt
│           ├── plugins/
│           │   ├── advhr/
│           │   │   ├── css/
│           │   │   │   └── advhr.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── rule.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   └── rule.htm
│           │   ├── advimage/
│           │   │   ├── css/
│           │   │   │   └── advimage.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── image.htm
│           │   │   ├── js/
│           │   │   │   └── image.js
│           │   │   └── langs/
│           │   │       └── en_dlg.js
│           │   ├── advlink/
│           │   │   ├── css/
│           │   │   │   └── advlink.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── advlink.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   └── link.htm
│           │   ├── advlist/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── autolink/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── autoresize/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── autosave/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── bbcode/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── contextmenu/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── directionality/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── emotions/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── emotions.htm
│           │   │   ├── js/
│           │   │   │   └── emotions.js
│           │   │   └── langs/
│           │   │       └── en_dlg.js
│           │   ├── example/
│           │   │   ├── dialog.htm
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── dialog.js
│           │   │   └── langs/
│           │   │       ├── en.js
│           │   │       └── en_dlg.js
│           │   ├── example_dependency/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── fullpage/
│           │   │   ├── css/
│           │   │   │   └── fullpage.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── fullpage.htm
│           │   │   ├── js/
│           │   │   │   └── fullpage.js
│           │   │   └── langs/
│           │   │       └── en_dlg.js
│           │   ├── fullscreen/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   └── fullscreen.htm
│           │   ├── iespell/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── inlinepopups/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── skins/
│           │   │   │   └── clearlooks2/
│           │   │   │       └── window.css
│           │   │   └── template.htm
│           │   ├── insertdatetime/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── layer/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── legacyoutput/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── lists/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── media/
│           │   │   ├── css/
│           │   │   │   └── media.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   ├── embed.js
│           │   │   │   └── media.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   ├── media.htm
│           │   │   └── moxieplayer.swf
│           │   ├── nonbreaking/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── noneditable/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── pagebreak/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── paste/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   ├── pastetext.js
│           │   │   │   └── pasteword.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   ├── pastetext.htm
│           │   │   └── pasteword.htm
│           │   ├── preview/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── example.html
│           │   │   ├── jscripts/
│           │   │   │   └── embed.js
│           │   │   └── preview.html
│           │   ├── print/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── save/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── searchreplace/
│           │   │   ├── css/
│           │   │   │   └── searchreplace.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── searchreplace.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   └── searchreplace.htm
│           │   ├── spellchecker/
│           │   │   ├── css/
│           │   │   │   └── content.css
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── style/
│           │   │   ├── css/
│           │   │   │   └── props.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── props.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   ├── props.htm
│           │   │   └── readme.txt
│           │   ├── tabfocus/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── table/
│           │   │   ├── cell.htm
│           │   │   ├── css/
│           │   │   │   ├── cell.css
│           │   │   │   ├── row.css
│           │   │   │   └── table.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   ├── cell.js
│           │   │   │   ├── merge_cells.js
│           │   │   │   ├── row.js
│           │   │   │   └── table.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   ├── merge_cells.htm
│           │   │   ├── row.htm
│           │   │   └── table.htm
│           │   ├── template/
│           │   │   ├── blank.htm
│           │   │   ├── css/
│           │   │   │   └── template.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── template.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   └── template.htm
│           │   ├── visualblocks/
│           │   │   ├── css/
│           │   │   │   └── visualblocks.css
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── visualchars/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── wordcount/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   └── xhtmlxtras/
│           │       ├── abbr.htm
│           │       ├── acronym.htm
│           │       ├── attributes.htm
│           │       ├── cite.htm
│           │       ├── css/
│           │       │   ├── attributes.css
│           │       │   └── popup.css
│           │       ├── del.htm
│           │       ├── editor_plugin.js
│           │       ├── editor_plugin_src.js
│           │       ├── ins.htm
│           │       ├── js/
│           │       │   ├── abbr.js
│           │       │   ├── acronym.js
│           │       │   ├── attributes.js
│           │       │   ├── cite.js
│           │       │   ├── del.js
│           │       │   ├── element_common.js
│           │       │   └── ins.js
│           │       └── langs/
│           │           └── en_dlg.js
│           ├── themes/
│           │   ├── advanced/
│           │   │   ├── about.htm
│           │   │   ├── anchor.htm
│           │   │   ├── charmap.htm
│           │   │   ├── color_picker.htm
│           │   │   ├── editor_template.js
│           │   │   ├── editor_template_src.js
│           │   │   ├── image.htm
│           │   │   ├── js/
│           │   │   │   ├── about.js
│           │   │   │   ├── anchor.js
│           │   │   │   ├── charmap.js
│           │   │   │   ├── color_picker.js
│           │   │   │   ├── image.js
│           │   │   │   ├── link.js
│           │   │   │   └── source_editor.js
│           │   │   ├── langs/
│           │   │   │   ├── en.js
│           │   │   │   └── en_dlg.js
│           │   │   ├── link.htm
│           │   │   ├── shortcuts.htm
│           │   │   ├── skins/
│           │   │   │   ├── default/
│           │   │   │   │   ├── content.css
│           │   │   │   │   ├── dialog.css
│           │   │   │   │   └── ui.css
│           │   │   │   ├── highcontrast/
│           │   │   │   │   ├── content.css
│           │   │   │   │   ├── dialog.css
│           │   │   │   │   └── ui.css
│           │   │   │   └── o2k7/
│           │   │   │       ├── content.css
│           │   │   │       ├── dialog.css
│           │   │   │       ├── ui.css
│           │   │   │       ├── ui_black.css
│           │   │   │       └── ui_silver.css
│           │   │   └── source_editor.htm
│           │   └── simple/
│           │       ├── editor_template.js
│           │       ├── editor_template_src.js
│           │       ├── langs/
│           │       │   └── en.js
│           │       └── skins/
│           │           ├── default/
│           │           │   ├── content.css
│           │           │   └── ui.css
│           │           └── o2k7/
│           │               ├── content.css
│           │               └── ui.css
│           ├── tiny_mce.js
│           ├── tiny_mce_popup.js
│           ├── tiny_mce_src.js
│           └── utils/
│               ├── editable_selects.js
│               ├── form_utils.js
│               ├── mctabs.js
│               └── validate.js
├── testing/
│   └── testdynamic.js
└── views/
    ├── cms/
    │   ├── comments-ajax.ejs
    │   ├── comments.ejs
    │   ├── contacts.ejs
    │   ├── content-type.ejs
    │   ├── dashboard.ejs
    │   ├── files-ajax.ejs
    │   ├── files.ejs
    │   ├── footer.ejs
    │   ├── forms-ajax.ejs
    │   ├── forms-data.ejs
    │   ├── forms-list.ejs
    │   ├── forms.ejs
    │   ├── header.ejs
    │   ├── images-ajax.ejs
    │   ├── images.ejs
    │   ├── navigation.ejs
    │   ├── pages-ajax.ejs
    │   ├── pages.ejs
    │   ├── styles.ejs
    │   ├── system.ejs
    │   ├── templates.ejs
    │   ├── top.ejs
    │   └── users.ejs
    ├── front/
    │   └── index.ejs
    └── login.ejs

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
#
# Project Exclude
#
.idea/
tests/
node_modules/
/doc/todo-jc.txt
#
# OS generated files
#
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
*.log



================================================
FILE: .npmignore
================================================
archive
bok
codyweb
jsconf
stef
stoerhuus


================================================
FILE: Contributing.md
================================================
Contributing
============

We are happy to accept your pull requests. If you do, make sure you clearly explain what and why you changed/added something so we can easily review it.

* Sadly enough we have no tests yet, but they will be coming soon.
* Make sure your code is linted and follow the general code style:
  * "" for strings
  * 2 whitespace indentation
  * named functions as much as possible
  * semi-colons!
  * name your captured this "self"


Guide to making a pull request can be found here: 


A shortened version goes as follows:

I assume you have git command-line installed, if not install from [here](http://git-scm.com/downloads).

1) **Fork** this repository by clicking the "Fork" in the upper corner of this page,
or by visiting this link: https://github.com/jcoppieters/cody/fork

2) **Clone** your forked repository (probably called linksgo2011/cody) on your local computer ([guide to cloning](https://github.com/jcoppieters/cody/compare/))

````
$ git clone https://github.com/jcoppieters/cody.git
````

3) Make a new branch with a name that conveys your change (e.g. "added-unicorns")

````
$ git checkout -b feature_branch_name
````

4) Make the changes you want to make on the files of the local repository.

5) **Commit** the changes. In your local repository do:

```` 
$ git add . -A
$ git commit -a -m "explain the changes you made. (e.g. I added unicorns)"
````

6) **Push** the changes to your forked repository on github. In your local repository do:

```` 
$ git push -u origin feature_branch_name
````

6) Submit a **Pull Request** by going to your repository on github and clicking the green arrows at the left top, or by visiting this link: https://github.com/jcoppieters/cody/compare/.
Choose your new branch to pull to the jcoppieters/master branch.





I hope this helps to get you started, if you got any question/problem along the way just shoot!

All the best.


================================================
FILE: History.md
================================================
# History
## 4.0.1..8 - 08/05/2025 - JC
* Use url prefix everywhere (also in the back-office !)
* fix forgotten password2 use
* don't use: xxx.url, use: xxx.getURL()
* better pool connection parameters for mysql
* change all the <% include xxx %> into <%- include("xxx") %>

*
## 4.0.0 - 06/05/2025 - JC
* Changed mysql to mysql2 library for mysql 8.x
* WARNING: if you use the mysql password function, change to password2 and add this function to your database:
    ```
  CREATE FUNCTION PASSWORD2(s VARCHAR(50))
     RETURNS VARCHAR(50) DETERMINISTIC
     RETURN CONCAT('*', UPPER(SHA1(UNHEX(SHA1(s)))));
    ```
* Upgrades of vulnerabilities:
     * Updating ejs to 3.1.10, which is a SemVer major change. 
     * Updating nodemailer to 7.0.2, which is a SemVer major change.
     * Updating multer to 1.4.5-lts.2, which is a SemVer major change.

## 3.4.5 - 11/05/2015 - TC
* Added mysql 5.7+ support for population script
* Fixed index.ejs, content.ejs and page.ejs for node 6+

## 3.4 - 25/08/2015 - TC
* Merged the pull request (i18n) of linksgo into the master branch. Chinese is now supported for the Cody interface and more languages can be added.

## 3.3.19 - 03/06/2015 - JC
* Added IP and path logging for the 3 app's. (starts with "LOG --A--", S and D for resp. Application, Static and Dynamic content requests)

## 3.3.17 - 20/05/2015
* Added an example controller to the empty site, removes the bug where the controller directory isn't tracked by git.


## 3.3.10 - 10/04/2015
* better setup, small corrections.

## 3.3.5 - 29/03/2015
* changed the directory structure to more reflect the hosting setup
* changes create script and you now have a startupscript in your cody-dev directory per project
> The user is no longer required to change the index.js afer scaffolding.

## 3.3.14 - 28/03/2015
* Added ContactController

## 3.3.5 - 20/01/2015
* Allow custom config file that overwrites the default config by supplying it on command-line with -c, by andretw. [Pull request](https://github.com/jcoppieters/cody/pull/17)

## 3.3.4 - 02/01/2015
* Security: prevent from loading static files outside of the public folder scope. [Issue](https://github.com/jcoppieters/cody/issues/16)

## 3.3.2 - 06/11/2014
* The scaffolding is now written in node, run with: $node ./node_modules/cody/bin/create_script

## 3.2.0 - 22/10/2014

* cccs -> create_script
* create_script now generates a config.json file that contains all the necessary configuration variables. They can be changed manually in the file or they can be overriden by setting the respective environment variables.
```bash
  $ dbuser=mydbuser dbpassword=mydbpassword port=8080 node index
```





================================================
FILE: LICENSE.md
================================================
The MIT License (MIT)

Copyright (c) 2015 Johan Coppieters - Howest.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.md
================================================
# Cody CMS

A Javascript Content Management System running on Node.js

We finally took upon the task, we are happy to announce the transition to Express 4 is now done! (dixit Slawo)

See http://www.cody-cms.com for more info and examples on http://github.com/jcoppieters/cody-samples

You can now use npm to install Cody thanks to Jonas.

## Features

* Node.js CMS
* Easy-to-use graphical interface + wysiwyg (what you see is what you get) editor that allows non-programmers to manage the site's *content*, *users*, *files*, *forms* and *images*.
* Tree structured GUI to manage the structure of the site and the editable content by using templates and drag-and-drop.
* Works seamless with your existing node.js code.


## Getting Started

By following these steps you will be running your own CMS system in no time. If any of the steps do not work for you, please report this as an issue on this github repository and we will look into it as soon as possible!

* Install [nodejs](http://nodejs.org/download/) and [mysql](http://dev.mysql.com/downloads/mysql/)
* Create a new directory for your cms and navigate to it (in unix):

  ```bash
	$ mkdir codydev
	$ cd codydev
  ```
* Install cody and its dependencies
  
  ```bash
	$ npm install cody
  ``` 

* Set up a new web site using the guided scaffolding

  ```bash
    $ node ./node_modules/cody/bin/create_site
    
    Creating cody web tree in current directory
    1) Enter sitename: mysite
    Note: also using my site as database name.
    Note: by default the mysql root user has no password so you can just hit enter, if you forgot the root password see http://dev.mysql.com/doc/refman/5.0/en/resetting-permissions.html
    2) Enter root password for mysql so we can create a new database and user: 
    3) Enter site database user: mysitename
    4) Enter site database password: mysitepassword
    5) Enter hostname for site: mysite.local (or localhost)
    Site mysite has been prepared.
    
    Please create DNS entries, or add to /etc/hosts:
    127.0.0.1     mysite.local
    
    Also check index.js and config.json to fine-tune extra parameters, encryption key, ...
    
    Start your site using:
    forever start mysite.js
    or
    node mysite.js
  ```
* Add a DNS entry for given hostname, e.g.

  ```bash
    $ sudo bash -c 'echo 127.0.0.1 mysite.local >> /etc/hosts'
  ```
* Run the server
  
  ```bash
    $ node mysite.js
  ```
  or if you want to automatically restart the server on changes
  
  ```bash
    $ forever start mysite.js
  ```
  
* Go to "http://mysite.local:3001" to see your current site and go to "http://mysite.local:3001/en/dashboard" to see the CMS of the site.

  the default users are: 'super', 'admin', 'test' and 'user' which all have password 'empty'
  you can ofcourse use "http://localhost:3001" too.


## Configuration

The create_site scaffolding creates a config.json file in the root of your project directory. This configuration can be adjust in the following three ways, listed in order of overwriting order (e.g. values of 2 will overwrite those of 1, etc.):

1. Manually adjust the values in the config.json file
2. Create your own config file and supply it at command-line with the -c option (since v3.2.5, thanks to [andretw](https://github.com/jcoppieters/cody/pull/17))
```bash
$ node index.js -c my_overwriting_config.json
```
3. Provide environment variables
```bash
$ dbuser=dbuser dbpassword=dbpassword port=8080 node index.js
```

Careful, all three cases need a server restart before they take effect!
Have a look at the generated config.json file to see which configuration variables you can use.


## Troubleshooting

##### I get "ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)" when running the scaffold script
  > Your mysql server is not started.
  
  * On Mac OS: go to "System Preferences" -> "Mysql" -> "Start"
  * On any unix machine: ```$ mysqld &```

##### After "5) Enter hostname for site" it prompts for "Enter password:"
  > You entered the incorrect password for your root user of the mysql database.
  
  Try to figure out the correct password or reset it: http://dev.mysql.com/doc/refman/5.0/en/resetting-permissions.html

## Contributors

  * Johan Coppieters
  * Jonas Maes
  * Tim Coppieters
  * Dieter
  * Laurens
  * Jelle

  * devoidfury
  * Andretw
  * You? We are always happy to review and accept your issues/pull requests!
  
## License

Copyright (c) 2012-2025 Johan Coppieters. See the LICENSE.md file for license rights and
limitations. This project is licensed under the terms of the MIT license.


Johan Coppieters, Jonas Maes - Tim Coppieters, VUB.


================================================
FILE: apps/Application.js
================================================
//
// Johan Coppieters - jan 2013 - jWorks
//
//


var mysql = require('mysql2');
// JM: assuming Application is always require()'d directly by cody/index.js since ../../index.js is ugly.
// maybe replace in all other files as well.
var cody = module.parent.exports;

console.log("loading " + module.id);


function Application(config) {
  this.templates = {};      // hashmap with (id - template)
  this.items = {};          // hashmap with (id - item)
  this.pages = [];          // array with all pages
  this.urls = {};           // hashmap with (urls - page)
  this.atoms = {};          // hashmap with (id - atom)
  this.languages = [];      // array with all languages
  this.domains = [];        // array with all (user) domains
  this.controllers = {};    // hashmap with (name - constructor)
    
  this.testing = config.testing || config.testing || false;
  this.logging = config.logging || config.logging || true;

  this.defaultlanguage = config.defaultlanguage || config.defaultlanguage || Application.kDefaultLanguage;
  Application.kDefaultLanguage = this.defaultlanguage;

  //TODO: don't we have to return errors if some of these are missing ?
  this.name = config.name || "cody";
  this.prefix = config.prefix || "";
  this.version =  config.version || "v1.0";
  this.datapath =  config.datapath || "./data";

  this.dbuser = config.dbuser || "cody";
  // allowing empty password, thanks linksgo2011 & ticup (changed also in template startup file: doc/empty/index.js)
  this.dbpassword = (typeof config.dbpassword === "undefined") ? "ydoc" : config.dbpassword;
  this.dbhost = config.dbhost || "localhost";
  this.dbport = config.dbport || 3306;
  this.db = config.db || "cody";
  this.smtp = config.smtp || "smtp.telenet.be";
  this.smtpoptions = config.smtpoptions; // see https://github.com/andris9/Nodemailer
  this.mailFrom = config.mailFrom || "info@cody-cms.org";

  this.dumpStructures = config.dumpstructures || true;
  if (this.logging) {
    console.log(this);
  }
}
module.exports = Application;

// Constants
Application.kDefaultLanguage = "en";

// Atom roots
Application.kImageRoot = 1;
Application.kFileRoot = 2;
Application.kFormRoot = 3;

// Content root id's
Application.kNoPage = -1;
Application.kHomePage = 1;
Application.kLoginPage = 2;
Application.kOrphansPage = 3;
Application.kFooterPage = 4;
Application.kDashboardPage = 9;
Application.kGlobalPage = 99;



Application.prototype.init = function( done ) {
  var self = this;

  self.getConnection();

  self.addControllers();
  
  // daisy chained loading of all CMS elements:
  //   languages, templates, atoms, items, pages with content,...
  self.fetchStructures( done );
};

Application.prototype.addController = function(name, controller) {
  var self = this;

  self.controllers[name] = controller;
};

Application.prototype.addControllers = function() {
  var self = this;
  var path = require('path')

  // add all controllers in the controller directory of cody
  // JM: module.parent = the invoking cody; its parent is the running
  // web app's module (user code).
  // note that path.resolve confuses the filename at the end of the
  // module path with a directory, so we need extra .. to refer to
  // the directory it is in.
  require("fs").readdirSync(path.resolve(module.parent.filename, '..', 'controllers/')).forEach(function(file) {
    var ctl = require(path.resolve(module.parent.filename, '..', 'controllers', file));
    self.addController(ctl.name, ctl);
  });


  // add alias 'ContentController' of 'Controller'
  self.addController("ContentController", self.controllers["controller"]);
 };


Application.prototype.err = function(p1, p2, res) {
  var self = this;

  console.log("*** error ***");
  self.log(p1, p2);
  
  if (typeof res !== "undefined") {
    res.writeHead(404, { "Content-Type": "text/plain" });
    res.write("404 Not Found\n");
    res.end();
  }
};
Application.prototype.log = function(p1, p2) {
  var self = this;

  if (self.logging) {
    if (typeof p1 === "undefined" && typeof p2 === "undefined") {
      console.log("Application -> ");
      console.log(this);
      
    } else if (typeof p2 === "undefined") {
      console.log(" - " + p1);
      
    } else {
      console.log(p1 + " -> " + p2);
    }
  }
};

Application.prototype.getDataPath = function() {
  return this.datapath;
};

///////////////
// Utilities //
///////////////
Application.endOfTime = function() {
	return new Date(2100,12,31,23,59,59);
};

Application.findFirst = function(theList) {
  var first = undefined;
  for (var f in theList) { 
    if (theList.hasOwnProperty(f)) {
      first = theList[f]; 
      break; 
    }
  }
  return first;
};

// Daisy chain operators
// - list should be an array
// - iterator is a function that should call the passed function when done
//   if it passes an error to the function the loop ends here
// - finished is a function that is called when everything is done with no parameter
//   or that is called when the first error occurs
//
// Example:
//   var list = [1, 2, 3, 4, 5];
//   var sum = 0;
//   Application.each(list, function(done) { 
//    sum += this; 
//    done();  // pass an error is something went wrong
//
//   }, function(err) { 
//     // do something with the err if any...
//     console.log("sum = " + sum);
//
//   });

Application.each = function(list, iterator, finished) {
  var nr = list.length;
  function one(current) {
   if (current >= nr) {
     finished();
     
   } else {
     iterator.call(list[current], function(err) {
       if (err) {
         finished(err);
       }
       one(current+1);
     });
   }
  }
  one(0);
};


// Daisy chain functions
// - functionList is a list of functions to be executed
// - each function is executed, with a callback function to be called at the end
// - if this callback is passed an error, the execution is terminated 
//   and the finish function will be called with this error
// - the finish function is called at the end with no error if everything went well
//
// Example:
//  var anObject = { nr: 0 };
//  var aList = [ [anObject, function(done) { this.nr++; done(); }], 
//                [anObject, function(done) { this.nr += 2; done(); }] ];
//  var nr = 0;
//  Application.doList(flist, function(err) { 
//    console.log("error ? " + err + ", total = " + anObject.nr); 
//  });
//
Application.doList = function(functionList, finished) {
  var nr = functionList.length;
  function one(current) {
   if (current >= nr) {
     if (typeof finished === "function") { finished(); }
     
   } else {
     var entry = functionList[current];
     entry[1].call( entry[0], function(err) {
       if (err) {
         if (typeof finished === "function") { finished(err); }
       }
       one(current+1);
     });
   }
  }
  one(0);
};

//////////////////
// Page serving //
//////////////////
Application.prototype.servePage = function(req, res) {
  var self = this;
  var url = (self.prefix) ? req._parsedUrl.pathname.substring(self.prefix.length+1) : req._parsedUrl.pathname;
  var path = new cody.Path(url, self.defaultlanguage);

  var ip = req.headers['x-forwarded-for'] ||
    req.connection.remoteAddress ||
    req.socket.remoteAddress ||
    req.connection.socket.remoteAddress;
  console.log("--LOG--A--|" + ip + "|" + new Date() + "|" + req.headers['host'] + "|" + req._parsedUrl.pathname);

  self.log("servePage - path -> " + path.link);
  
   
  var aContext = self.buildContext( path, req, res );
  if (typeof aContext !== "undefined") {
    self.handToController(aContext);
  }
};


Application.prototype.buildContext = function (path, req, res) {
  var self = this;
  
  // get the page
  var page = self.findPage(path);
  
  if (typeof page === "undefined") {
      self.err("servePage", "No page found for path = " + path.pagelink, res);
      return undefined;
  }

  self.log("buildContext -> page", page.language + "/" + page.itemId + " - " + page.title);
  
  // build a context
  var context = new cody.Context(path, page, self, req, res);
  console.log("servePage - params -> "); console.log(context.params);
  console.log("servePage - session -> "); console.log(context.session);

  if (typeof req.files !== "undefined") { console.log("servePage - files -> "); console.log(req.files); }

  return context;
};

Application.prototype.handToController = function(context) {
  var self = this;
  
  // make a controller and send it 'doRequest'
  self.log("handToController", context.page.item.template.controllerName);
  var controller = context.page.getController(context);
  
  if (typeof controller === "undefined") {
    self.err("handToController", "No controller found for " + context.page.item.template.controllerName);
    return;
  }
  
  // check if authentication is required for this action
  //  and if so and not yet done: store this action and perform login first
  if (controller.needsLogin()) {
    if (controller.isLoggedIn()) {
      self.log("Application - check login", "already logged in");
      if (! controller.isAllowed(context.page)) {
        controller.close();
        self.notAllowed(context);
        return;
      }
    } else {
      self.log("Application - check login", "needs login, redirect/remember");

      controller.close();
      self.logInFirst(context);
      return;
    }
  }
  
  controller.doRequest( function(fn, header) {
    // callback function should always be called by doRequest
    //  render with the specified or the template in the context (controller may have changed it)
    //  if no render template present ( == "") either
    //    -- assume the controller performed res.writeHead() / .write() / .end() -- ajax req?
    //    -- another controller has taken over

    if (typeof fn === "object") {
      controller.gen(fn, header);
      
    } else {
      if (typeof fn !== "undefined") {
        context.fn = fn; 
      }
      
      self.log("Application.handToController -> finished -> render view", (context.fn==="") ? "** none **" : context.fn);

      self.renderView( context );
    }
      
    controller.close();
  });
};

Application.prototype.renderView = function( context ) {
  var self = this;
  var path = require("path");

  if (context.fn === "") {
    return;
  }

  // cody views can be used by starting the pathname with "-/"
  var i = context.fn.indexOf("-/");

  // default root path for rendering in Express = [project]/views/
  // JM: module.parent = the invoking cody; its parent is the running
  // web app's module (user code).
  // note that path.resolve confuses the filename at the end of the
  // module path with a directory, so we need extra .. to refer to
  // the directory it is in.
  var viewfile = (i === 0) ?
      path.resolve(module.parent.filename, "..", "views", context.fn.substring(2)) :
      path.resolve(module.parent.parent.filename, "..", "..", self.name, "views", context.fn);

  self.log("Application.renderView", viewfile);
  context.res.render(viewfile, context);
};

// internal redirect = delegate
Application.prototype.delegate = function(context, redirectTo) {
  var self = this;

  // either [language]/itemlink or itemlink
  var newURL = (redirectTo.indexOf("/") != 2) ? context.page.language + "/" + redirectTo : redirectTo;
  var aPath = new cody.Path(newURL, self.defaultlanguage);
  var aContext = self.buildContext( aPath, context.req, context.res );
  self.handToController(aContext);
};

Application.prototype.logInFirst = function(context) {

  // copy minimal version of the context to our session
  context.req.session.pendingContext = context.getMini();

  this.delegate(context, "login");
};

Application.prototype.notAllowed = function(context) {
  this.delegate(context, "notallowed");
};


/////////////////
// SQL support //
/////////////////
//
// Shouldn't we use a connection pool instead of a single connection?
//
// const pool = mysql.createPool({
//   host: 'localhost',
//   user: 'root',
//   database: 'test',
//   waitForConnections: true,
//   connectionLimit: 5,
//   queueLimit: 0
// })
// const users = await pool.query('SELECT * FROM users');


//
// Advise from chatGPT:
// •	Reconnects on dropped connections via .on('error')
// •	Keeps the TCP socket alive with enableKeepAlive
// •	Prevents idle disconnects via ping() every 30s
// •	Avoids multiple setInterval() timers
// •	Fails fast during startup if the DB is unreachable, letting PM2 restart
//

Application.prototype.getConnection = function() {
  var self = this;

  function connectToDatabase() {
    return mysql.createConnection({
      host: self.dbhost, port: self.dbport,
      user: self.dbuser, password: self.dbpassword,
      database: self.db,
      multipleStatements: true, supportBigNumbers: true,
      ssl: undefined, connectTimeout: undefined,

      // connection pool settings
      // connectionLimit: 16, waitForConnections: true, queueLimit: 50,

      // this keeps the tcp socket alive
      keepAliveInitialDelay: 10000, enableKeepAlive: true
    });
  }

  if ((!self.connection) || (self.connection.state === 'disconnected')) {
    self.log("Application", "Make new Connection");
    
    self.connection = connectToDatabase();

    // reconnect on disconnect
    self.connection.on('error', err => {
      console.error('MySQL error', err);
      if (err.code === 'PROTOCOL_CONNECTION_LOST') {
        console.log('Reconnecting after connection lost: ', err);
        self.connection = connectToDatabase();
      }
    });

    // this keeps the connection alive (not the OS socket)
    self._intervalTimer = self._intervalTimer || setInterval(() => {
      self.connection.ping(err => {
        if (err) {
          console.error('Reconnecting after MySQL ping error: ', err);
          self.connection = connectToDatabase();
        }
      });
    }, 30000);

  } else {
    self.log("Application.getConnection", "Returning existing connection");
  }
  
  if (!self.connection) {
    // PM2 will restart the app if this happens
    throw(new Error("Fatal error: No database connection"));
  }

  return self.connection;
};


Application.prototype.returnConnection = function( connection ) {
  // Do nothing: we only have 1 connection and we don't close it in between requests...
  
};

///////////////////////////////////////////
// Fetch all structured data into memory //
///////////////////////////////////////////
Application.prototype.fetchStructures = function( done ) {
  var self = this;

  Application.doList([
    [self, Application.prototype.fetchLanguages],
    [self, Application.prototype.fetchAtoms],
    [self, Application.prototype.fetchTemplates],
    [self, Application.prototype.fetchItems],
    [self, Application.prototype.fetchPages],
    [self, Application.prototype.fetchDomains]
  ], function(err){
    if (err) {
      self.log("fetchStructures", "!! some of our loading functions failed !!");
    } else {
      self.log("fetchStructures", "finished loading the database structures");
      if (self.dumpStructures) { self.dump(); }
      if (typeof done === "function") { done (); }
    }
  });
};

///////////////
// Languages //
///////////////
Application.prototype.fetchLanguages = function(done) {
  var self = this;
  
  cody.Page.loadLanguages(self.connection, function(result) {
    for (var i in result) {
      if (result.hasOwnProperty(i)) {
        self.languages.push(result[i]);
        if (typeof self.defaultlanguage === "undefined") self.defaultlanguage = result[i].id;
      }
    }
    self.log("Application.fetchLanguages", "fetched " + result.length + " languages");
    
    // next step
    done();
  });
};

Application.prototype.getLanguages = function() {
	return this.languages;
};
Application.prototype.isDefaultLanguage = function(language) {
  return language === this.defaultlanguage;
};


///////////
//Atoms //
///////////
Application.prototype.getAtom = function(id) {
  return this.atoms[id];
};

Application.prototype.addAtom = function(atom) {
  var self = this;

  self.atoms[atom.id] = atom;
  atom.app = self;
};

Application.prototype.hasAtomChildren = function(parent) {
  var self = this;

  for (var i = 0; i < self.atoms.length; i++) {
    if  (self.atoms[i].parent === parent.id) {
      return true;
    }
  }
  return false;
};
Application.prototype.getAtomChildren = function(parent) {
  var self = this;

  var list = [];
  for (var i in self.atoms) {
    var anAtom = self.atoms[i];
    if (parent.isChild(anAtom)) {
      list.push(anAtom);
    }
  }
  list.sort( function(a, b) { return a.sortorder - b.sortorder; });
  return list;
};

Application.prototype.fetchAtoms = function(done) {
  var self = this;

  //fetch all atoms
  cody.Atom.loadAtoms(self.connection, function(result) {
    self.atoms = {};
    for (var i = 0; i < result.length; i++) {
      self.addAtom(new cody.Atom(result[i]));
    }
    self.log("Application.fetchAtoms", "fetched " + result.length + " atoms");

    // next step
    done();
  });
};


///////////////
// Templates //
///////////////
Application.prototype.getTemplate = function(templateId) {
  return this.templates[templateId];
};
Application.prototype.fetchTemplates = function(done) {
  var self = this;
  
  cody.Template.loadTemplates(self.connection, function(result) {
    self.templates = {};
    for (var i = 0; i < result.length; i++) {
      // make an Template object of our data
      var O = new cody.Template(result[i], self.controllers);
      
      // store under its id
      self.templates[O.id] = O;
    }
    self.log("Application.fetchTemplates", "fetched " + result.length + " templates");
    
    // next step
    done();
  });
};

Application.prototype.templateUsed = function(templateId) {
  var found = false;

  for (var it in this.items) {
    if (this.items[it].templateId == templateId) {
      return true;
    }
  }
  return false;
};

Application.prototype.deleteTemplate = function(templateId) {
  var self = this;

  var aTemplate = self.templates[templateId];
  if (typeof aTemplate !== "undefined") {
    delete self.templates[templateId];
  }
  return aTemplate;
};

///////////
// Items //
///////////
Application.prototype.getItem = function(itemId) {
  return this.items[itemId];
};
Application.prototype.attachItemChildren = function() {
  var self = this;

  // loop through all items and attach their parent
  for (var i in self.items) {
    // let the page itself pick from the list
    self.items[i].pickParent(self.items);
  }
};

Application.prototype.addItem = function(anItem) {
  var self = this;
  
	self.items[anItem.id] = anItem;
	anItem.pickParent(self.items);
  self.log("Application.addItem", "added " + anItem.id + " / " + anItem.name);
};

Application.prototype.fetchItems = function(done) {
  var self = this;
  
  cody.Item.loadItems(self.connection, function(result) {
    // make hashtable on item id
    self.items = {};
    
    for (var i = 0; i < result.length; i++) {
      // make an Item object of our data
      var O = new cody.Item(result[i], self);
      
      // store under its id
      self.items[O.id] = O;
    }
    self.attachItemChildren();

    self.log("Application.fetchItems", "fetched " + result.length + " items");
    // console.log(self.items);
    
    // next step
    done();
  });
};


///////////
// Pages //
///////////
Application.prototype.getPage = function(languageOrLink, itemId) {
  var self = this;

  var link = languageOrLink;
  if (typeof itemId !== "undefined") {
    link += "/"+itemId;
  }
  return self.urls[link];
};

Application.prototype.findPage = function(path) {
  var self = this;

  // hash based on only language/domain

  // if only language is specified (can be the defaultlanguage), serve the welcome/home page
  var aPage = self.urls[path.pagelink + ((path.domain === "") ? "welcome" : "")];
  
  // if page not found -> serve the language/notfound page
  if (typeof aPage === "undefined") {
    console.log("Application.findPage - not found -> " + path.pagelink + ", trying -> " + path.language + "/notfound");
    aPage = self.urls[path.language + "/notfound"];
  }

  if (typeof aPage !== "undefined") {
    aPage = aPage.getDisplay();
  }
  
  return aPage;
};


Application.prototype.genRoots = function() {
  var self = this;

  // loop through all pages and lookup its 'toplevel' (root)
  for (var i in self.pages) {
    self.pages[i].addRoot();
  }  
};


Application.prototype.attachChildrenToPages = function() {
  var self = this;

  // loop through all pages and attach their children
  for (var i in self.pages) {
    // let the page itself pick from the list
    self.pages[i].addChildren(self.pages);
  }
};


Application.prototype.buildSitemap = function() {
  var self = this;

  self.attachChildrenToPages();
  self.genRoots();
};


Application.prototype.addPage = function(page) {
  var self = this;

  page.addTo(self);
	self.buildSitemap();
};


Application.prototype.fetchPages = function(done) {
  var self = this;
  
  cody.Page.loadPages(self.connection, function(result) {
    self.pages = [];
    self.urls = {};
    
    Application.each(result, function(nextOne) {
      
      var onePage = new cody.Page(this, self);
      self.log("Application.fetchPages", onePage.title);
      
      onePage.addTo(self);
      onePage.loadContent(self, nextOne);

    }, function(err) { 
      self.buildSitemap();
      
      self.log("Application.fetchPages", "fetched " + result.length + " pages");
      
      // next step
      done();
    });
  });
};


Application.prototype.deletePagesForItem = function( itemId, finish ) {
  var self = this;
  
  // delete the pages in every language from the url hashmap
  for (var i in self.languages) {
    var lan = self.languages[i].id;
    var P = self.getPage(lan, itemId);
    delete self.urls[lan+"/"+itemId];
    if (P.link !== "") {
      delete self.urls[lan+"/"+P.link];
    }
  }
  
  // delete the page from the pages array
  // by rebuilding the array while omitting the pages
  var newList = [];
  for (var p in self.pages) {
    if (self.pages[p].itemId != itemId) {
      newList.push(self.pages[p]);
    }
  }
  self.pages = newList;
  
  // rebuild the tree structure
  self.buildSitemap();
  
  finish();
};


Application.prototype.dump = function() {
  var self = this;
  var cnt = 0;
  
  function printPage(lan, id) {
    var p = self.getPage(lan, id);
    if (p) {
      console.log(" " + p.shortString());
    } else {
      console.log(" ** missing page **");
    }
  }

  function printLevel(r, nr) {
    var tab = "";
    for (var i=0; i<nr; i++) { tab = tab + " "; }

    for(var p in r) {
      console.log(tab + r[p].shortString());
      cnt += r[p].contentLength();
      printLevel(r[p].children, nr+2);
    }
  }
  function printChildren(lan, id) {
    console.log("- " + lan + " -");
    var p = self.getPage(lan, id);
    printLevel(p.getChildren() , 1);
  }
 
  console.log("--- Controllers ---");
  for (var c in self.controllers) {
    console.log(c);
  }
  
  console.log("\n--- Homepages ---");
  self.languages.forEach( function(lan) { printChildren(lan.id, Application.kHomePage); });
  
  console.log("\n--- Dashboard ---");
  self.languages.forEach( function(lan) { printChildren(lan.id, Application.kDashboardPage); });
  
  console.log("\n--- Footers ---");
  self.languages.forEach( function(lan) { printChildren(lan.id, Application.kFooterPage); });
  
  console.log("\n--- Pages ---");
  self.languages.forEach( function(lan) { printChildren(lan.id, Application.kOrphansPage); });
  
  console.log("\n--- Globals ---");
  self.languages.forEach( function(lan) { printPage(lan.id, Application.kGlobalPage); });
  
  console.log("\n--- Logins ---");
  self.languages.forEach( function(lan) { printPage(lan.id, Application.kLoginPage); });

  
  console.log("\n----------------");
  console.log("Total content: " + cnt + " bytes");
  console.log("----------------");
};



/////////////////////
//Users - Domains //
/////////////////////
Application.prototype.fetchDomains = function(done) {
  var self = this;
  
  // fetch all user domains
  cody.User.getDomains(self.connection, function(result) {
    self.storeDomains(result);
    self.log("Application.fetchDomains", "fetched " + result.length + " domains");
    
    // next step
    done();
  });
};


Application.prototype.storeDomains = function(result) {
  var self = this;
  self.domains = [];
  for (var i = 0; i < result.length; i++) {
    self.domains.push(result[i].domain);
  }
};


================================================
FILE: apps/Dynamic.js
================================================
//
// Johan Coppieters - jan 2013 - jWorks
//
//
console.log("loading " + module.id);

var libpath = require("path"),
    http = require("http"),
    fs = require("fs"),
    url = require("url"),
    mime = require("mime"),
    cody = require("../index.js");

var maxCacheAge = 600;  // 10 minutes  ???


function generate404(resp) {
  resp.writeHead(404, { "Content-Type": "text/plain" });
  resp.write("404 Not Found\n");
  resp.end();
}

function Dynamic(req, res, path, prefix) {
  this.request = req;
  this.response = res;
  this.path = path;
  this.prefix = prefix || "";
}

module.exports = Dynamic;


Dynamic.prototype.serve = function () {
  var self = this;
  var uri = url.parse(self.request.url).pathname;

  // remove prefix
  if (self.prefix && (uri.indexOf("/"+self.prefix) === 0)) {
    uri = uri.substring(self.prefix.length+1);
  }

  var ip = self.request.headers['x-forwarded-for'] ||
    self.request.connection.remoteAddress ||
    self.request.socket.remoteAddress ||
    self.request.connection.socket.remoteAddress;
  console.log("--LOG--D--|" + ip + "|" + new Date() + "|" + self.request.headers['host'] + "|" + self.request._parsedUrl.pathname);

  uri = uri.replace("data/", "");
  var filename = libpath.normalize(libpath.join(this.path, uri));

  // check for malicious paths -- thanks to Tom Hunkapiller
  if (filename.indexOf(this.path) !== 0) {
    console.log("Dynamic.serve -> malicious path: " + uri);
    generate404(self.response);
    return;
  }


  // check if this file exists
  fs.exists(filename, function (exists) {
      if (!exists) {
        console.log("Dynamic.serve -> file not found: " + filename);
        generate404(self.response);
        return;
      }

      fs.readFile(filename, "binary", function (err, file) {
        if (err) {
          console.log("Dynamic.serve -> error reading: " + filename + " - " + err);
          self.response.writeHead(500, { "Content-Type": "text/plain" });
          self.response.write(err + "\n");
          self.response.end();
          return;
        }

        var type = mime.lookup(filename);
        console.log("Dynamic.serve -> reading: " + filename + " - " + file.length + " bytes as " + type);
        self.response.writeHead(200, {
          "Content-Type": type,
          "Cache-Control": "public, max-age=" + maxCacheAge
        });
        self.response.write(file, "binary");
        self.response.end();
      });
  });
};


================================================
FILE: apps/Static.js
================================================
//
// Johan Coppieters - jan 2013 - jWorks
//
//
console.log("loading " + module.id);

var libpath = require("path"),
    http = require("http"),
    fs = require("fs"),
    url = require("url"),
    mime = require("mime");
 
var path = ".";

var cache = {},
    nrCache = 0,
    maxCache = 1, //1 is good for developement -> 30 seems to be reasonable for small websites.
    maxCacheAge = 86400;


function Static(req, res, appFolder, prefix) {
  this.request = req;
  this.response = res;
  this.appFolder = appFolder;
  this.prefix = prefix || "";

  //TODO: we need to have a cache per application
  // - the cody static cache should be high (100?)
  // - other application could be very small (10? 20?)

  //if (typeof cacheSize !== "undefined") {
  //  cache[appFolder].maxCache = cacheSize;
  //}
}
module.exports = Static;


Static.prototype.dump = function () {
  this.response.writeHead(200, { "Content-Type": "text/plain" });
  this.response.write("Cache dump\n----------\n");
  var cnt = 0;
  for (var c in cache) {
    if (cache.hasOwnProperty(c)) {
      this.response.write(c + ": " + cache[c].length + " bytes\n");
      cnt += cache[c].length;
    }
  }
  this.response.write("---------------------------\n");
  this.response.write("Total bytes cached: " + cnt + " bytes\n");
  this.response.write("---------------------------\n");
  this.response.end();
};

Static.prototype.addCache = function (filename, file) {
  if (nrCache >= maxCache) {
    // should be sorted on number of uses
    var nr = Math.floor(Math.random() * maxCache) + 1;
    for (var c in cache) {
      if (cache.hasOwnProperty(c)) {
        nr--;
        if (nr === 0) {
          delete cache[c];
          nrCache--;
          // console.log("static -> deleted from cache: " + c);
          break;
        }
      }
    }
  }
  cache[filename] = file;
  nrCache++;
  // console.log("Static -> added to cache: " + filename);
};


Static.prototype.tryCache = function (filename) {
  var file = cache[filename];
  if (file) {
    // add 1 to nr of uses
    var type = mime.lookup(filename);
    console.log("Static.serve -> cache hit: " + filename + " - " + file.length + " bytes as " + type);
    this.response.writeHead(200, {
      "Content-Type": type,
      "Cache-Control": "public, max-age=" + maxCacheAge // thanks Aselbie
    });
    this.response.write(file, "binary");
    this.response.end();
    return true;
  }
  return false;
};


Static.prototype.serve = function () {
  var self = this;
  var uri = url.parse(self.request.url).pathname;

  // remove prefix
  if (self.prefix && (uri.indexOf("/"+self.prefix) === 0)) {
    uri = uri.substring(self.prefix.length+1);
  }

  var ip = self.request.headers['x-forwarded-for'] ||
    self.request.connection.remoteAddress ||
    self.request.socket.remoteAddress ||
    self.request.connection.socket.remoteAddress;
  console.log("--LOG--S--|" + ip + "|" + new Date() + "|" + self.request.headers['host'] + "|" + self.request._parsedUrl.pathname);

  var filename;

  // JM: module.parent = the invoking cody; its parent is the running
  // web app's module (user code).
  // note that path.resolve confuses the filename at the end of the
  // module path with a directory, so we need extra .. to refer to
  // the directory it is in.
  if (self.appFolder != "") {
    filename = libpath.resolve(module.parent.parent.filename, "..", "..", self.appFolder, uri.substring(1));
  }
  else
  {
    //JM: requested a file from cody's static files.
    //the first part of the uri must be "/cody" (or actually we compare with
    //the current cody module's package's directory name).
    if(uri.indexOf("/" + libpath.basename(libpath.resolve(module.parent.filename, "..")) + "/") == 0)
    {
	filename = libpath.resolve(module.parent.filename, "..", uri.substring(libpath.basename(libpath.resolve(module.parent.filename, "..")).length + 2));
    }
    else
    {
	console.log("Invalid URI: " + uri);
	return;
    }
  }

  // should be moved to a SystemController
  if (filename === "static/_") {
    this.dump();
    return;
  }
    
  // try serving from cache
  if (self.tryCache(filename)) {
    return;
  }
  
  // check if this file exists
  fs.exists(filename, function (exists) {
      if (!exists) {
        console.log("Static.server -> file not found: " + filename);
        self.response.writeHead(404, { "Content-Type": "text/plain" });
        self.response.write("404 Not Found\n");
        self.response.end();
        return;
      }

      if (fs.statSync(filename).isDirectory()) {
        filename += '/index.html';
      }

      fs.readFile(filename, "binary", function (err, file) {
        if (err) {
          console.log("Static.serve -> error reading: " + filename + " - " + err);
          self.response.writeHead(500, { "Content-Type": "text/plain" });
          self.response.write(err + "\n");
          self.response.end();
          return;
        }

        var type = mime.lookup(filename);
        console.log("Static.serve -> sending: " + filename + " - " + file.length + " bytes as " + type);
        self.response.writeHead(200, {
          "Content-Type": type,
          "Cache-Control": "public, max-age=" + maxCacheAge
        });
        self.response.write(file, "binary");
        self.response.end();
        
        self.addCache(filename, file);
      });
  });
};


================================================
FILE: bin/create_site.js
================================================
// Tim & Jonas V1.0 -- running from within the cody project directory
//
// Johan: v1.1 -- using path, creating a startup file in the root dir of cody projects, ...
//                this resembles the hosting setup.


var readline = require("readline");
var util     = require("util");
var fs       = require("fs");
var mysql    = require("mysql2");
var path     = require("path");

var rootwd = process.cwd();
var codywd = rootwd + "/node_modules/cody";

// https://gist.github.com/tkihira/3014700
var mkdir = function (dir) {
  // making directory without exception if exists
  try {
    fs.mkdirSync(dir, 0755);
  } catch (e) {
    if (e.code !== "EEXIST") {
      throw e;
    }
  }
};

var copyDir = function (src, dest) {
  mkdir(dest);
  var files = fs.readdirSync(src);
  var i;
  for (i = 0; i < files.length; i++) {
    var current = fs.lstatSync(path.join(src, files[i]));
    if(current.isDirectory()) {
      copyDir(path.join(src, files[i]), path.join(dest, files[i]));
    } else if(current.isSymbolicLink()) {
      var symlink = fs.readlinkSync(path.join(src, files[i]));
      fs.symlinkSync(symlink, path.join(dest, files[i]));
    } else {
      copy(path.join(src, files[i]), path.join(dest, files[i]));
    }
  }
};

var copy = function (src, dest) {
  var oldFile = fs.createReadStream(src);
  var newFile = fs.createWriteStream(dest);
  oldFile.pipe(newFile);
};

/**
 * Look ma, it's cp -R.
 * @param {string} src The path to the thing to copy.
 * @param {string} dest The path to the new copy.
 */
var copyRecursiveSync = function(src, dest) {
  // console.log(src + " -> " + dest);
  var exists = fs.existsSync(src);
  var stats = exists && fs.statSync(src);
  var isDirectory = exists && stats.isDirectory();
  if (fs.existsSync(dest)) return;
  if (exists && isDirectory) {
    console.log("mkdir " + dest);
    fs.mkdirSync(dest);
    fs.readdirSync(src).forEach(function(childItemName) {
      copyRecursiveSync(path.join(src, childItemName),
        path.join(dest, childItemName));
    });
  } else {
    fs.linkSync(src, dest);
  }
};


var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

console.log("\nCreating project in ", rootwd + "/");

rl.question("\n1) Enter projectname: ", function (sitename) {
  console.log("Note: also using " + sitename + " as database name.");
  console.log("Note: by default the mysql root user has no password so you can just hit enter, if you forgot the root password http://dev.mysql.com/doc/refman/5.0/en/resetting-permissions.html");
  
  rl.question("\n2) Enter root password for mysql so we can create a new database and user: ", function (dbrootpw) {
    
    rl.question("\n3) Enter site database user: ", function (dbuser) {
      
      rl.question("\n4) Enter site database password: ", function (dbpass) {

        rl.question("\n5) Enter dbhost for db: ", function (dbhost) {
             
          rl.question("\n6) Enter hostname for site: ", function (hostname) {
          var con = mysql.createConnection({
            host: dbhost,
            user: dbuser,
            password: dbpass,
            multipleStatements: true
          });

          rl.question("\n7) Enter a location for storing documents: ", function (datadir) {
          
            console.log("dbhost is "+dbhost);
            con.connect();
            con.query("create database " + sitename + " default charset utf8", function (err) {
              if (err) console.log(err);
              con.query("grant all on " + sitename + ".* to '" + dbuser + "'@'%' identified by '" + dbpass + "'", function (err) {
                if (err) console.log(err);

                con.query("grant all on " + sitename + ".* to '" + dbuser +"'@'"+ dbhost + " identified by '" + dbpass + "'", function (err) {
                  if (err) console.log(err);

                  con.end();
                  con = mysql.createConnection({
                    host: dbhost,
                    user: dbuser,
                    database: sitename,
                    password: dbpass,
                    multipleStatements: true
                  });
                  console.log("dbhost is "+dbhost);
                  con.connect();

                  mkdir(path.join(rootwd, sitename));
                    fs.readdirSync(codywd + "/doc/empty").forEach(function (src) {
                      copyRecursiveSync(path.join(codywd,"doc","empty", src), path.join(rootwd, sitename , src));
                    });

                    fs.readFile(path.join(rootwd, sitename, "empty.sql"), function (err, initstatements) {
                      if (err) throw err;

                      con.query(initstatements.toString(), function (err) {
                        if (err) throw err;

                        fs.writeFileSync(path.join(rootwd, sitename, "config.json"), JSON.stringify(
                          { name: sitename,
                            mailFrom: "info@"+hostname,
                            hostnames:"localhost,"+hostname,
                            db: sitename,
                            dbuser: dbuser,
                            dbpassword: dbpass,
                            dbhost: dbhost,
                            smtp: "smtpmailer."+hostname,
                            version: "V0.1",
                            defaultlanguage: "en",
                            datapath: "/usr/local/data/"+sitename,
                            port: 3001
                          }));
                        //copy(path.join(rootwd, sitename, "index.js"), path.join(rootwd, sitename+".js"));
                        //fs.unlinkSync(path.join(rootwd, sitename, "index.js"));


                        mkdir(datadir);
                        mkdir(path.join(datadir,sitename));
                        console.log("created "+datadir+"/"+sitename+"/");
                        mkdir(path.join(datadir,sitename,"images"));
                        console.log("created "+datadir+"/"+sitename+"/images");
                        mkdir(path.join(datadir,sitename,"files"));
                        console.log("created "+datadir+"/"+sitename+"/files");


                        console.log("---")
                        console.log("Site '" + sitename + "' has been prepared.\n")
                        console.log("Please create DNS entries, or add to /etc/hosts:");
                        console.log("127.0.0.1     " + hostname);
                        console.log("Also check index.js and config.json to fine-tune extra parameters, encryption key, ...");
                        console.log("---")
                        console.log("Start your site using:");
                        console.log("$ forever start " + sitename + ".js");
                        console.log("    or");
                        console.log("$ node " + sitename + ".js");
                        console.log("-");
                        console.log("surf to http://localhost:3001");
                        console.log("    or manage your site at");
                        console.log("http://localhost:3001/en/dashboard");
                        console.log("    for mysql8 users:");
                        console.log("CREATE FUNCTION PASSWORD2(s VARCHAR(50))\n RETURNS VARCHAR(50) DETERMINISTIC\n RETURN CONCAT('*', UPPER(SHA1(UNHEX(SHA1(s)))));");

                        con.end();
                        rl.close();
                      });
                    });
                });
              });
            });
          });
        });
        });
      });
    });
  });
});


================================================
FILE: bin/remove_site
================================================
#!/bin/bash

# this is rubbish...  "Creating tree... dropping the database..."
# we should look at the config.json
#   and remove the used directories (asking confirmation for each one)
#   and drop the database in the config file

exit


realpkgroot="${PWD}/node_modules/cody"
echo Creating cody web tree in current directory
echo -n "1) Enter sitename: "
read sitename
echo -n "2) Enter site database user: "
read dbuser
echo "Note: the mysql root password is empty by default (just press enter)"
echo -n "3) Enter mysql root password: "
read dbrootpw
read -n "Are you sure you want to delete ${sitename}? [y/n]"
read proceed

if [proceed]; then
  mysql --user=root "--password=$dbrootpw" -e "drop database $sitename"
  mysql --user=root "--password=$dbrootpw" -e "drop user $dbuser"

  echo "Site '$sitename' database has been removed."
fi

================================================
FILE: controllers/ContactController.js
================================================
//
// Johan Coppieters - first integration into cody code base 29/03/2015
//
// alpha 1: uses Model, CRUD operations are working
// planned:
//  - alpha 2: dynamic tags, add tag
//  - alpha 3: send mail
//  - alpha 4: copy from data.data (JSON) -> contacts, JSON.rest -> contacts.data
// beta 1: add template to "empty"
//
//

/* SQL tables

drop table tags;
create table tags (
 id char(16) not null primary key,
 name varchar(63)
 );
insert into tags values ('jsconf', 'jsconf.be'), ('stage', 'Stage'), ('cody', 'Cody'), ('ITmgrs', 'ICT Mgrs');

drop table contacts;
create table contacts (
 id int(11) not null primary key auto_increment,
 company varchar(127) default '',
 name varchar(127) default '',
 title varchar(32) default '',
 street varchar(127) default '',
 zipcity varchar(127) default '',
 country varchar(64) default '',
 email varchar(127) default '',
 phone varchar(32) default '',
 phone2 varchar(32) default '',
 origin varchar(32) default '',
 tags varchar(255) default '',
 active char(1) default 'Y',
 note varchar(2048) default '',
 nomail char(1) default 'N',
 data text
);

 */
console.log("loading " + module.id);

var cody = require("cody/index.js");



function ContactController(context) {
  console.log("ContactController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);

  // make a contact model and attach to controller
  var myModel = new cody.Model(this, {
    tableName: "contacts",
    id: {name: "id", def: 0},
    cols: [
      {name: "name",   label: "Name",        def: "",  list: true,  sort: "asc", q: "like"},
      {name: "company",label: "Company",     def: "",  list: true,  q: "like" },
      {name: "title",  label: "Title",       def: "",  list: false},
      {name: "street", label: "Street",      def: "",  list: false},
      {name: "zipcity",label: "Zip City",    def: "",  list: false},
      {name: "country",label: "Country",     def: "",  list: false},
      {name: "tags",   label: "Tags",        def: "",  list: false, q: "like"},
      {name: "email",  label: "Email",       def: "",  list: true,  q: "like"},
      {name: "data",   label: "JSON Data",   def: "{}",list: false},
      {name: "phone",  label: "Phone 1",     def: "",  list: true},
      {name: "phone2", label: "Phone 2",     def: "",  list: true,  hide: true},
      {name: "origin", label: "Origin",      def: "",  list: false},
      {name: "note",   label: "Note",        def: "",  list: false},
      {name: "active", label: "Active",      def: "Y", list: true,  hide: true},
      {name: "nomail", label: "Allows Mail", def: "Y", list: true,  hide: true}]
  });

  this.model.addRef("tags", "select id, name from tags order by name");
  this.model.addRef("atoms", "select id, name from atoms where parent = 3 order by name");

  context.model = myModel;

	// init inherited controller
	cody.Controller.call(this, context);
}

ContactController.prototype = Object.create( cody.Controller.prototype );
module.exports = ContactController;



ContactController.prototype.doRequest = function( finish ) {
  var self = this;

  self.getDetailData();

  if (this.doCrudRequest(finish)) {
    // handled by std controller

  } else if (this.isRequest("sendmail")) {
    self.doMails(function() {
      self.model.doList( finish );
    });

  } else if (this.isRequest("testmail")) {
    self.doTestMail(function() {
      self.model.doList( finish );
    });

  } else if (this.isRequest("import")) {
    self.doImportFormData(self.context.atom, self.context.status, function() {
      self.model.doList( finish );
    });

  } else {
    cody.Controller.prototype.doRequest.call(self, finish);

  }
};


ContactController.prototype.getDetailData = function() {
  var self = this;

  // search params
  self.context.q_name = self.updateSession("q_name", "");
  self.context.q_company = self.updateSession("q_company", "");
  self.context.q_tags = self.updateSession("q_tags", "");
  self.context.q_email = self.updateSession("q_email", "");

  // current status and form id
  self.context.status = self.updateSession("status", "N");
  self.context.atom = self.updateSession("atom", 0);

  // get mail data
  self.context.subject = this.updateSession("subject", "");
  self.context.content = this.updateSession("content", "");
  self.context.testmail = this.updateSession("testmail", "");
  self.context.testname = this.updateSession("testname", "");

  self.context.tagCheckboxes = function(name, selected) {
    var html = "";
    var nr = 0;
    for (var iT in this.tags) {
      var tag = this.tags[iT];
      html += '<input name="' + name + '" id="tag' + nr + '" type="checkbox" value="' + tag.id + '" ' +  this.checked(selected.indexOf(tag.id)>=0) + ' /><label for="tag' + nr + '">' + tag.name + '</label>';
      nr++;
    }
    return html;
  }
};


ContactController.prototype.doImportFormData = function (atomId, status, finished) {
  // formdata sits in the "data" table, having
  // id, atom, data(json), status(N/T/D/A), created, modified
  //
  // we'll copy the "created" date, put the name of the atom in "source"
  // we set the active = 'Y', nomail = 'N'
  // from the JSON data we'll try to extract:  name, company(cie), title, tags, email, phone(phone1,telephone), phone2
  //  note(remark), street, zipcity(city), country
  // we'll store the rest of the JSON string in the "data" field.

  function ffield(obj, nameArr) {
    var val = "";
    nameArr.forEach(function(el) {
      if (typeof obj[el] !== "undefined") {
        if (val === "") val = obj[el];
        delete obj[el]; // side effect... delete the field
      }
      var El = el.charAt(0).toUpperCase() + el.slice(1);
      if (typeof obj[El] !== "undefined") {
        if (val === "") val = obj[El];
        delete obj[El]; // side effect... delete the field
      }
    });
    return val;
  }
  var self = this;
  var atom = self.app.getAtom(atomId);
  var tags = self.getParam("tags");
  if (Array.isArray(tags)) tags = tags.join(",");

  self.query("select data, status, created from data where atom = ? and status = ?", [atomId, status], function(err, results) {
    if (err) {
      console.log("error selecting data with status="+ status + " and atom=" + atomId + " -> " + err);
      self.feedBack(false, "Error fetching data from the forms");
      finished();

    } else {
      console.log("importing " + results.length + " records.");
      cody.Application.each(results, function(done) {
        console.log("using data: " + this.data);
        var json = JSON.parse(this.data);
        var arr = [ffield(json, ["cie", "company"]),
                   ffield(json, ["name"]),
                   ffield(json, ["title"]),
                   ffield(json, ["street"]),
                   ffield(json, ["zipcity", "zipCity", "city"]),
                   ffield(json, ["country"]),
                   ffield(json, ["mail", "email"]),
                   ffield(json, ["phone", "telephone", "phone1", "mobile", "gsm"]),
                   ffield(json, ["phone2", "home"]),
                   atom.name,
                   tags,
                   "Y",
                   ffield(json, ["note","remark"]),
                   "N",
                   JSON.stringify(json)];
        console.log(arr);
        self.query("insert into contacts " +
          "(company, name, title, street, zipcity, country, email, phone, phone2, origin, tags, active, note, nomail, data) " +
          "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", arr, done);

      }, function(err) {
        if (err) {
          console.log("error inserting data -> " + err);
          self.feedBack(false, "Error inserting data");
        } else {
          self.feedBack(true, results.length + " records added");
        }

        finished();
      });
      for (var iRec in results) {
        var rec = results[iRec];

      }
    }
  });
}


ContactController.prototype.doTestMail = function (finished) {
  var pSubject = this.getParam("subject", "testing");
  var pName = this.getParam("testname", "testname");
  var email = this.getParam("testmail", "testing@cody-cms.org");
  var pFrom = this.app.mailFrom;
  var pText = this.getParam("content","cody-cms.org testing");
  //self.sendMail (pFrom, C.email, pSubject, pText);
  console.log ("mailto: from=" + pFrom + ", to=" + pName + " - " + email + " - " +  pSubject + " - " +  pText);
}

ContactController.prototype.doMails = function (finished) {
  this.sendTargetMails(finished, this.getParam("q_tags", ""),
                                 this.app.mailFrom,
                                 this.getParam("subject", "testing"),
                                 this.getParam("content","cody-cms.org testing"));
}


ContactController.prototype.sendTargetMails = function (finished, tags, pFrom, pSubject, pText) {
  var self = this;

  var p = "";
  var ps = [];
  if (Array.isArray(tags)) {
    for(var it in tags) {
      p = p + ((it == 0) ? "where " : " or ") + "tags like ?";
      ps.push("%"+tags[it]+"%");
    }
  }
  console.log("Sending email from " + pFrom + " to contacts with tags: " + tags + " -> " + p);

  self.query("select * from contacts " + p, ps, function(err, result) {
    if (err) { console.log("error selecting contacts with tags "+ tags + " -> " + err); } else {

      for (var iC in result) {
        var C = result[iC];
        //self.sendMail (pFrom, C.email, pSubject, pText);
        console.log ("mailto: from=" + pFrom + ", to=" + C.name + " - " + C.email + " - " +  pSubject + " - " +  pText);
      }
    }
    finished();
  });

};

================================================
FILE: controllers/Controller.js
================================================
//
// Johan Coppieters - jan 2013 - jWorks
//
//
console.log("loading " + module.id);

var mysql = require("mysql2");
var nodemailer = require("nodemailer");
var cody = require("../index.js");


function Controller(context) {
  // only called for using my methods
  if (typeof context === "undefined") { return; }
  if (context.page) {
    console.log("Controller.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);

    this.addParamsToContext(context);
  }

  this.context = context;
  context.controller = this;

  this.app = context.app;
  this.connection = (this.app) ? this.app.getConnection() : undefined;

  // console.log(this.context);
}

module.exports = Controller;

Controller.prototype.close = function() {
  this.closeConnection();
};


//
// core handler
//

Controller.prototype.doRequest = function( finish ) {
  console.log("Controller.doRequest -> request = " + this.getRequest());
  //console.log(this.context);

  // if you don't want any rendering to be done:
  //  pass an empty string (or set this.context.fn to empty)

  if (! this.hasSubmittedForm(finish)) {
    finish();
  }
};

Controller.prototype.doCrudRequest = function( finish ) {
  var self = this;

  if (typeof self.model === "undefined") return false;

  if (self.isRequest("") || this.isRequest("list")) {
    self.model.doList( finish );

  } else if (self.isRequest("save")) {
    self.model.scrapeFrom(self);
    self.model.doSave( function() {
      self.nextRequest("list", finish);
    });

  } else if (self.isRequest("delete")) {
    self.model.doDelete( this.getId(), function() {
      self.nextRequest("list", finish);
    });

  } else if (this.isRequest("edit")) {
    self.model.doGet( this.getId(), finish);

  } else if (this.isRequest("new")) {
    self.model.doGet( NaN, finish );

  } else {
    return false;
  }

  return true;
};


Controller.prototype.isRequest = function(theString) {
  return (this.getRequest(true) === (theString || "").toUpperCase());
};
Controller.prototype.setRequest = function(theString) {
  if (this.context) {
    this.context.request = theString;
  }
};
Controller.prototype.getRequest = function(upper) {
  var req = (this.context && this.context.request) || "";
  if (Array.isArray(req)) req = req.at(-1) || "";
  return (upper) ? req.toUpperCase() : req;
};


Controller.prototype.getId = function(defaultValue) {
  // if there is a model connected to this controller, use the attributes of model.id
  var idname = (typeof this.model !== "undefined") ? this.model.id.name : "id";
  if (defaultValue === undefined) defaultValue = (typeof this.model !== "undefined") ? this.model.id.def : -1;

  var x = this.context.getParam(idname);
  x = (typeof x === "undefined") ? NaN : parseInt(x, 10);

  if (isNaN(x)) {
    x = this.context.path.id;
    x = (x === undefined) ? NaN : parseInt(x, 10);
  }

  return isNaN(x) ? defaultValue : x;
};


//
// ask another controller to handle the current (changed) request
//   = internal redirect ( <-> this.redirect )
//
Controller.prototype.delegate = function(link) {
  this.close();
  this.app.delegate(this.context, link);
};

//
// Ask same controller/page to handle another request
//  prevents post requests from being re-executed
//   = external redirect
//
Controller.prototype.nextRequest = function(err, request, finish) {
  var self = this;
  // if only 2 parameters, assume that no "err" was passed.
  if (typeof finish === "undefined") {
    finish = request; request = err; err = null;
  }

  if (err) {
    // don't do the redirect... let's hope the current view is going to display the error
    //  change the view to error.ejs ??
    self.feedback(false, err);
    finish();
  } else {
    self.redirect("/" + this.context.page.getURL() + "/" + request, finish);
  }
};

// real redirect handled by the server
//   = external redirect ( <-> this.delegate )
Controller.prototype.redirect = function(url, finish) {
  this.context.res.redirect(url);
  if (typeof finish === "function") finish("");
};


//
// User login stuff -- most of the time proxied to the context object 
//

Controller.prototype.needsLogin = function() {
  return (this.context) && (this.context.page) && (this.context.page.needsLogin());
};
Controller.prototype.isLoggedIn = function() {
  return (this.context) && (this.context.isLoggedIn());
};
Controller.prototype.getLogin = function() {
  return (this.context) ? (this.context.getLogin()) : new cody.User({});
};
Controller.prototype.setLogin = function(theUser) {
  if (this.context) {
    this.context.setLogin(theUser);
  }
};

Controller.prototype.getLoginId = function() {
  var login = this.getLogin();
  return (login) ? login.id : undefined;
};
Controller.prototype.getLoginLevel = function() {
  var login = this.getLogin();
  return (login) ? login.level : 0;
};


Controller.prototype.isAllowed = function( theItemOrPage ) {
  var aUserDomain = this.getLogin().getDomain();
  var anItemDomain = theItemOrPage.getAllowedDomains();

  console.log("Controller.isAllowed: user = '" + aUserDomain + "', item/page(" + theItemOrPage.getId() + ") = '" + anItemDomain + "'");

  // no userdomain -> not allowed
  if (aUserDomain === "") { return false; }

  // user has all rights or belongs to cody admin
  if ((aUserDomain === "*") || (aUserDomain === "cody")) { return true; }

  // item can be edited by any domain or no specific domains are set up
  if ((anItemDomain === "*") || (anItemDomain === "")) { return true; }

  // there is a user domain and the item has 1 of more domain
  // loop through them all and check to see if there is a correspondence
  var aList = anItemDomain.split(",");
  for (var x in aList) {
    if (aList[x]===aUserDomain) {
      return true;
    }
  }

  return false;
};



//
// Form handling
//
Controller.prototype.hasSubmittedForm = function(finish) {
  var self = this;

  // check if a form was submitted (request = send, form-atom = atom.id)
  var atomId = self.getParam("form-atom", 0);

  if ((self.isRequest("send")) && (atomId != 0)) {
    var anAtom = this.app.getAtom(atomId);
    console.log("Controller.doRequest: submitted form = " + atomId + " -> " + anAtom.name);

    // construct a meta data object
    var form = cody.FormController.makeMeta(anAtom, self.page);

    // have the meta object read the values from the submitted params
    form.readValuesFrom(self.context.params, false);
    if (form.ok) {
      // signal if everything was ok and no form is needed again
      self.context.submitted = true;

      // save the values in a database
      form.saveValues(self, "N", finish);

      self.alertFormOwner(anAtom, form);

    } else {
      // store the meta object + it's values for re-displaying
      if (typeof self.context.errorForms === "undefined") {
        self.context.errorForms = {};
      }
      // to be used instead of an empty form
      self.context.errorForms[atomId] = form;
      finish();
    }
    return true;
  }
  return false;
};


Controller.prototype.alertFormOwner = function(atom, form) {
  var self = this;

  var lan = self.context.page.language;
  var formDesc = JSON.parse(atom.note);

  if ((typeof formDesc.alert != "undefined") && (formDesc.alert != "")) {
    var mail = "Dear webmaster,\n\nA user of the app: '" + atom.app.name + "' submitted a form: '" + formDesc.labels[lan] + "' with values:\n\n";
    for (var iE in form.objects) { var element = form.objects[iE];
      if (typeof element.options.choices !== "undefined") {
        mail += element.labels[lan] + ": " + element.options.choices[lan][element.value] + "\n";
      } else {
        mail += element.labels[lan] + ": " + element.value + "\n";
      }
    }
    mail += "\n\nYour website.\n";
    self.sendMail(self.app.mailFrom, formDesc.alert, "Message from " + atom.app.name, mail);
  }
};

Controller.prototype.sendMail = function (pFrom, pTo, pSubject, pText, pHtml, finished) {
  // for the moment we don't wait for the smtp transfer to be completed
  // so we can't generate error feedback to the user, perhaps make a version with a callback too?
  var self = this;

  // swap params
  if (typeof pHtml === "function") {
    finished = pHtml;
    pHtml = undefined;
  }

  console.log("Sending email from " + pFrom + " to " + pTo);

  var mailOptions = {
      from: pFrom, // sender address
      to: pTo, // list of receivers
      subject: pSubject // Subject line
  };
  var hasText = (typeof pText !== "undefined") && (pText) && (pText !== "");
  if (hasText) {
    mailOptions.text = pText;
  }
  if ((typeof pHtml !== "undefined") && (pHtml) && (pHtml !== "")) {
    mailOptions.html = pHtml;
  }

  // create transport options -- smtp defaults
  var options = {
      host: self.context.app.smtp,
      secureConnection: false,
      port: 25
    };
  // if the smtp-options are defined in the config, use these instead of the older 'separate'/'default' style
  if (typeof self.app.smtpoptions != "undefined") {
    options = self.app.smtpoptions;
  }
  // allow the authentication params to be defined separately
  if (typeof self.app.smtpauth != "undefined") {
    options.auth = self.app.smtpauth;
  }

  console.log(" connecting to " + options.host);
  var smtpTransport = nodemailer.createTransport(options);

  smtpTransport.sendMail(mailOptions, function (error, info) {
      if (error) {
          console.log("Error sending mail: " + error);
      } else {
          console.log("Message sent: " + info.response);
      }
    if (typeof finished === "function") finished();
  });
};

//
// Session handling
//
Controller.prototype.fromSession = function(paramName, defaultValue) {
  return this.context.fromSession(paramName, defaultValue);
};

Controller.prototype.toSession = function(paramName, value) {
  this.context.toSession(paramName, value);
};

Controller.prototype.updateSession = function(paramName, defaultValue) {
  var value = this.getParam(paramName, this.context.fromSession(paramName, defaultValue));
  this.context.toSession(paramName, value);
  return value;
};

//
// Parameter handling
//
Controller.prototype.getParam = function(paramName, defaultValue) {
  return this.context.getParam(paramName, defaultValue);
};


Controller.prototype.getDate = function(paramName, defaultValue) {
  var x = this.context.getParam(paramName);
  return this.context.makeDate(x, defaultValue);
};

Controller.prototype.makeDate = function(value, defaultValue) {
  return this.context.makeDate(value, defaultValue);
}


Controller.prototype.getInt = function(paramName, defaultValue) {
  var x = this.context.getParam(paramName);
  return this.makeInt(x, defaultValue);
};

Controller.prototype.makeInt = function(value, defaultValue) {
  return this.context.makeInt(value, defaultValue);
}

Controller.prototype.getNum = function(paramName, defaultValue, precision) {
  var x = this.context.getParam(paramName);
  return this.makeNum(x, defaultValue, precision);
};

Controller.prototype.makeNum = function(value, defaultValue, precision) {
  return this.context.makeNum(value, defaultValue);
}


Controller.prototype.getUNum = function(paramName, defaultValue) {
  var anId = this.context.getParam(paramName);
  if ((typeof anId === "undefined") || (anId === "")) {
    return (typeof defaultValue === "undefined") ? 0 : defaultValue;
  } else  {
    var i = anId.indexOf("_");
    if (i >= 0) {
      return parseInt(anId.substring(i+1), 10);
    } else {
      return parseInt(anId, 10);
    }
  }
};


//
// Query stuff
//

Controller.prototype.query = function(sql, params, callback) {
  // callback = function(error, results)

  this.connection.query(sql, params, callback);
};
Controller.prototype.escape = function(v){
    return this.connection.escape(v);
}

Controller.prototype.closeConnection = function() {
  // console.log("Controller -> done with database connection");

  if (this.connection) {
    this.app.returnConnection(this.connection);
    this.connection = undefined;
  }
};


// General utilities

Controller.prototype.addParamsToContext = function( context ) {
  //TODO: what if there are more than 1 content settings blocks attached?
  var content = context.page.content;
  for (var iC in content) {
    if ((content.hasOwnProperty(iC)) && (content[iC].kind === "P")) {
        context.settings = JSON.parse(content[iC].data);
    }
  }
}

//
// Output & feedback utilities
//
Controller.prototype.render =  function( theContent ) {
  this.app.log("Controller", "ERROR ** attempt to render a content with kind = '" +  theContent.kind + "' and no renders provided");

  return "<!-- unknown content type = " + theContent.kind + ", atomId = " + theContent.atomId + ", data = " + theContent.data + "-->";
};

Controller.prototype.gen = function( theContent, theHeader ) {
  if (typeof theHeader === "undefined") {
    this.context.res.writeHead(200, { "Content-Type": "application/json" });
  } else {
    this.context.res.writeHead(200, theHeader);
  }

  if (typeof theContent !== "string") {
    this.context.res.write(JSON.stringify(theContent));
  } else {
    this.context.res.write(theContent);
  }
  this.context.res.end();
};

Controller.prototype.feedBack = function(success, message) {
  this.context.status = (success) ? "success" : "error";
  this.context.message = message;
  this.context.xmessage = message;
  this.context.success = success;
};
Controller.prototype.feedback = Controller.prototype.feedBack;



================================================
FILE: controllers/DashboardController.js
================================================
//
// Johan Coppieters - may 2013 - cody
//
//
console.log("loading " + module.id);

var cody = require("../index.js");


function DashboardController(context) {
  console.log("DashboardController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);

	// init inherited controller
	cody.Controller.call(this, context);
}

DashboardController.prototype = Object.create( cody.Controller.prototype );
module.exports = DashboardController;



DashboardController.prototype.doRequest = function( finish ) {
  var self = this;
  
  finish();
};




================================================
FILE: controllers/EmailController.js
================================================
//
// Laurens Ramandt - june 2013 - cody
//
//

// this class abstracts nodemailer, just in case we would switch from nodemailer to something else
// npm install nodemailer required

var nodemailer = require("nodemailer");
var cody = require("./../index.js");
function EmailController (context) {
    console.log("EmailController construct");
    cody.Controller.call(this, context);
}

EmailController.sendEmail = function (pFrom, pTo, pSubject, pText) {
    console.log("Sending email from " + pFrom + " to " + pTo);

    var mailOptions = {
        from: pFrom, // sender address
        to: pTo, // list of receivers
        subject: pSubject, // Subject line
        html: pText // HTML body
    };

    //TODO: for production, modify this to use /usr/bin/sendmail
    var smtpTransport = nodemailer.createTransport("SMTP", {
        host: "smtp.scarlet.be", //change this to match your server
        secureConnection: false,
        port: 25/*,
         auth: {
         user: "user@domain.com",
         pass: "password"
         }                   */
    });

    smtpTransport.sendMail(mailOptions, function (error, response) {
        if (error) {
            console.log("Error sending mail: " + error);
        } else {
            console.log("Message sent: " + response.message);
        }
    });

};


EmailController.prototype = Object.create( cody.Controller.prototype );
module.exports = EmailController;

================================================
FILE: controllers/FileController.js
================================================
//
// Johan Coppieters - jan 2013 - jWorks
//
//
var mysql = require("mysql2");
var cody = require('../index.js');

console.log("loading " + module.id);


function FileController(context) {
  console.log("FileController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);
  
  // init inherited controller
  cody.TreeController.call(this, context);
  
}

FileController.prototype = Object.create( cody.TreeController.prototype );
module.exports = FileController;



FileController.prototype.doRequest = function( finish ) {
  var self = this;
  
  if (self.isRequest("xxx")) {
    // needed ?
    finish("");

  } else {
    cody.TreeController.prototype.doRequest.call(self, finish);
    
  }
};


FileController.prototype.getRoot = function() {
  return cody.Application.kFileRoot;
};
FileController.prototype.getType = function(theNode) { 
  return ((theNode.extention === "xxx") || (theNode.extention === "")) ? "folder" : "file"; 
};
FileController.prototype.getObject = function(id) {
  return this.app.getAtom(id);
};
FileController.prototype.getFolder = function() { 
  return "/files"; 
};


/* Overridden - Action functions */




================================================
FILE: controllers/FormController.js
================================================
//
// Johan Coppieters - jan 2013 - jWorks
//
//
var mysql = require("mysql2");
var cody = require('../index.js');

console.log("loading " + module.id);


FormController.makeMeta = function( atom ) {
  var elements = (atom) ? atom.getChildren() : [];
  var arr = [];
  for (var iE in elements) {
    arr.push(elements[iE].note);
  }
  var form = new cody.Meta();
  form.metaId = atom.id;
  form.addList(arr);
  return form;
};

FormController.makeFormInfo = function( atom, page ) {
  var formInfo = (atom && atom.note && (atom.note.length > 2)) ? JSON.parse(atom.note) : {};
  if (typeof formInfo.url === "undefined") {
    formInfo.url = page.getURL(page.language);
  }
  return formInfo;
};

FormController.menuList = function( atoms, current ) {
  var root = atoms[cody.Application.kFormRoot];

  var options = "";
  var currId = (current) ? current.id : 0;
  var aList = root.getChildren();
  for (var x in aList) {
    options += "<option value='" + aList[x].id + "'" + ((currId == aList[x].id) ? " selected" : "") + ">" + aList[x].name + "</option>";
  }
  // console.log("current = " + currId + ", menuPopup -> " + options);
  return options;
};

function FormController(context) {
  console.log("FormController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);
  
  // init inherited controller
  cody.TreeController.call(this, context);
  
}

FormController.prototype = Object.create( cody.TreeController.prototype );
module.exports = FormController;



FormController.prototype.doRequest = function( finish ) {
  var self = this;

  cody.TreeController.prototype.doRequest.call(self, finish);
};


FormController.prototype.getRoot = function() {
  return cody.Application.kFormRoot;
};
FormController.prototype.getType = function(theNode) { 
  return ((theNode.extention === "xxx") || (theNode.extention === "")) ? "form" : "item";
};
FormController.prototype.getObject = function(id) {
  return this.app.getAtom(id);
};
FormController.prototype.getFolder = function() { 
  return "/forms";
};


/* Overridden - Action functions */
FormController.prototype.emptyLabels = function(isForm) {
  var self = this;
  var labels = {};
  for (var iL in self.app.languages) {
    labels[self.app.languages[iL].id] = (isForm) ? "Send" : self.context.atom.name;
  }
  if (isForm) {
    labels["nl"] = "Verstuur";
    labels["fr"] = "Envoyer";
    labels["de"] = "Versenden";
  }
  return labels;
};


FormController.prototype.isMultiple = function( aGenerator ) {
  return ((aGenerator === cody.Meta.Generator.checkboxinput) ||
          (aGenerator === cody.Meta.Generator.selectinput) ||
          (aGenerator === cody.Meta.Generator.radioinput));
};


// overridden function for forms
FormController.prototype.fetchNode = function( theNode, finish ) {
  var self = this;


  cody.TreeController.prototype.fetchNode.call(this, theNode, function() {
    var isForm = (self.context.atom.extention === "");
    console.log("FormController.FetchNode: node = " + theNode + " -> " + self.context.atom.name + " / " + self.context.atom.extention);

    // get the definitions from the "note" field in the atoms
    var obj = { name: self.context.atom.name, options: {}, labels: self.emptyLabels((self.context.atom.extention === "")), generator: 1 };

    // add email alert address for forms.
    if (isForm) { obj.alert = ""; }

    try {
      var tryObj = JSON.parse(self.context.atom.note);
      if ((typeof tryObj !== "undefined") && (tryObj)) { obj = tryObj; }
    } catch(e) {
    }
    self.context.object = obj;

    if (isForm) {
      // a form, nothing more needed.
      finish();

    } else {
      // an item

      if (typeof obj.options === "undefined") {
        obj.options = {};
      }

      // the options below are shown in 2 fields called min/max
      if (obj.generator == cody.Meta.Generator.textareainput) {
        obj.min = (typeof obj.options.cols === "undefined") ? "" : obj.options.cols;
        obj.max = (typeof obj.options.rows === "undefined") ? "" : obj.options.rows;
      } else {
        obj.min = (typeof obj.options.minimum === "undefined") ? "" : obj.options.minimum;
        obj.max = (typeof obj.options.maximum === "undefined") ? "" : obj.options.maximum;
      }
      if (self.isMultiple(obj.generator)){
        if (typeof obj.options.choices !== "undefined") {
          for (var iC in obj.options.choices) {
            var C = obj.options.choices[iC];
            var X = "";
            for (var iL in C) {
              X += iL + "|" + C[iL] + "\n";
            }
            obj.options.choices[iC] = X.slice(0, -1);
          }
        }
      }
      finish();
    }
  });
};



// overridden function for forms
//
// Read all meta definitions from the posted form
//  1) decide what reader should be taken, based on the "generator"
//    + some parameters (phone, number, email, date, date3)
//  2) read labels
//  3) read choices (for checkboxes, radio's, popup's)
//  4) read specific options (required, default value, ...)
//
// Finally store in an atom/object

FormController.prototype.saveInfo = function( nodeId, finish ) {
  var self = this;
  console.log("FormController.saveInfo: node = " + nodeId );

  var anObject = this.getObject(cody.TreeController.toId(nodeId));
  if (typeof anObject !== "undefined") {

    // read the basics for an atom and for an form/item
    anObject.scrapeFrom(this);
    var obj = { name: anObject.name, labels: {} };

    // read the labels in all languages
    for (var iL in self.app.languages) {
      var L = self.app.languages[iL].id;
      obj.labels[L] = this.getParam("label-"+L, "");
    }

    // We use the extension field in the atom table to make the difference between forms and form-items.
    if (anObject.extention === "") {
      // form
      obj.alert = self.getParam("alert", "");
      self.context.shownode = anObject.id;
      self.context.opennode = anObject.id;

    } else {
      // item
      self.context.shownode = anObject.parentId;
      self.context.opennode = anObject.parentId;

      // next (long) section fills in the correct values for "generator" and "options"
      // depending on the user's choice of the different parameters (required, validation, generator, min/max, ...)
      var aGenerator = parseInt(self.getParam("generator", cody.Meta.Generator.textinput), 10);
      obj.generator = aGenerator;
      obj.options = {};
      obj.reader = cody.Meta.Reader.string;

      var defV = this.getParam("default", "");
      if (defV !== "") {
        obj.options.default = defV;
      }

      if ((this.getParam("required", "N") === "Y") &&
          (aGenerator !== cody.Meta.Generator.checkboxinput)) {
        obj.options.required = true;
      }

      // add validation text or number
      var validation = this.getParam("validation", "X");
      if ((aGenerator === cody.Meta.Generator.textinput) ||
          (aGenerator === cody.Meta.Generator.textareainput)) {
        if (validation === "E") {
          obj.options.email = true;
          obj.reader = cody.Meta.Reader.email;
        } else if (validation === "P") {
          obj.options.phone = true;
          obj.reader = cody.Meta.Reader.phone;
        }
      } else if (aGenerator === cody.Meta.Generator.numberinput) {
        obj.options.number = true;
        if (validation === "I") {
          obj.reader = cody.Meta.Reader.integer;
        } else { // === "N"
          obj.reader = cody.Meta.Reader.number;
        }
      }

      // add min/max or cols/rows
      var aMin = self.getParam("min", "");
      var aMax = self.getParam("max", "");
      if (aGenerator === cody.Meta.Generator.textareainput) {
        if (aMin !== "") { obj.options.cols = aMin; }
        if (aMax !== "") { obj.options.rows = aMax; }
      } else if ((aGenerator === cody.Meta.Generator.numberinput) || (aGenerator === cody.Meta.Generator.textinput)) {
        if (aMin !== "") { obj.options.minimum = aMin; }
        if (aMax !== "") { obj.options.maximum = aMax; }
      }

      // add choices in all languages
      // there is one field (choice-[language]) for every language
      // one choice per line and possibly in the format "[id]|[label]"
      // the user can enter his list without "[id]|", we will add it on next edit
      if (this.isMultiple(aGenerator)){
        if (aGenerator === cody.Meta.Generator.checkbox) {
          obj.reader = cody.Meta.Reader.multiple;
        }
        obj.options.choices = {};

        for (var iL in self.app.languages) {
          var L = self.app.languages[iL].id;
          obj.options.choices[L] = {};
          var arr = self.getParam("choice-"+L, "").replace("\r", "").split("\n");

          if (arr[0].indexOf("|") > 0) {
            // user has given keys value pairs
            for (var i in arr) {
              var cInx = arr[i].indexOf("|");
              var cID = arr[i].substring(0, cInx);
              obj.options.choices[L][cID] = arr[i].substring(cInx+1);
            }
          } else {
            // no keys, only choices, we'll label them 0, 1, 2 ,...
            for (var i in arr) {
              obj.options.choices[L][i] = arr[i];
            }
          }
        }
      }

      // Date readers (1 field or 3 fields)
      if (aGenerator === cody.Meta.Generator.dateinput) {
        obj.reader = cody.Meta.Reader.date;
      } else if (aGenerator === cody.Meta.Generator.date3input) {
        obj.reader = cody.Meta.Reader.date3;
      }

    }
    console.log("show / open -> " + self.context.shownode + " / " + self.context.opennode);
    var str = JSON.stringify(obj);
    console.log("Generated Meta: " + str);
    anObject.note = str;
    anObject.doUpdate(self, finish);

  } else {
    this.feedBack(false, "failed to save the data");
    finish();
  }
};


================================================
FILE: controllers/FormDataController.js
================================================
//
// Johan Coppieters - sept 2013 - cody
//
//
console.log("loading " + module.id);

var cody = require("../index.js");


function FormDataController(context) {

  // init inherited controller and add all instance variables
  cody.Controller.call(this, context);
}

FormDataController.prototype = Object.create( cody.Controller.prototype );
module.exports = FormDataController;



FormDataController.prototype.doRequest = function( finish ) {
  var self = this;
  if (self.isRequest("")) { self.setRequest("list"); }

  var id = this.getParam("id", 0);
  var meta = this.getParam("meta", 0);

  console.log("FormDataController.constructor -> id = " + id + ", meta = " + meta + ", request = " + self.context.request);


  if (self.isRequest("save")) {
    self.saveData(id, meta, function() {
      self.context.fn = "-/cms/forms-list.ejs";
      self.listData(finish);
    });

  } else if (self.isRequest("delete")) {
      self.deleteData(id, function() {
        self.context.fn = "-/cms/forms-list.ejs";
        self.listData(finish);
      });

  } else if (self.isRequest("list")) {
    self.context.fn = "-/cms/forms-list.ejs";
    self.listData(finish);

  } else if (this.isRequest("edit")) {
    self.context.fn = "-/cms/forms-data.ejs";
    self.editData(meta, id, finish);

  } else if (this.isRequest("sendmail")) {
    self.context.fn = "-/cms/forms-list.ejs";
    self.sendAllMail(finish);

  } else if (this.isRequest("testmail")) {
    self.context.fn = "-/cms/forms-list.ejs";
    self.sendTestMail(finish);

  } else {
    cody.Controller.prototype.doRequest.call(self, finish);
  }

};

FormDataController.prototype.getDetailData = function() {
  var self = this;

  // current status and form id
  self.context.form_show = self.updateSession("form_show", "N");
  self.context.form_meta = self.updateSession("form_meta", 0);

  // get mail data
  self.context.subject = this.updateSession("subject", "");
  self.context.content = this.updateSession("content", "");
  self.context.testmail = this.updateSession("testmail", "");
  self.context.testname = this.updateSession("testname", "");
};


FormDataController.prototype.personalize = function(text, params) {
  // write generic replace... who???
  if (typeof params.Name != "undefined")
    text = text.replace("[name]", params.Name).replace("[Name]", params.Name);
  if (typeof params.name != "undefined")
    text = text.replace("[name]", params.name).replace("[Name]", params.name);

  return text;
}

FormDataController.prototype.sendAllMail = function(finish) {
  var self = this;
  var nr = 0;

  // fetch list & detail data
  self.listData(function() {
    // loop over self.content.data and send mails...
    cody.Application.each(self.context.data,
      function(done) {
        var body = self.personalize(self.context.content, this.data);

        // allow "email", "Email", "Mail" or "mail" in the formdata.
        var email =
          (typeof this.data.Email != "undefined") ? this.data.Email :
          (typeof this.data.email != "undefined") ? this.data.email :
          (typeof this.data.Mail  != "undefined") ? this.data.Mail :
          (typeof this.data.mail  != "undefined") ? this.data.mail : "";

        if (email !== "") {
          self.sendMail(self.app.mailFrom, email,
                        self.context.subject, body, function() {
            nr++;
            done();
          });
        } else {
          done();
        }
      },
      function(err) {
        if (err) console.log("something went wrong: " + err);
        console.log("Sent " + nr + " mails");
        self.feedBack(true, "Sent " + nr + " mails");
        finish();
      });
  });
};

FormDataController.prototype.sendTestMail = function(finish) {
  var self = this;

  // fetch list & detail data
  self.listData(function() {

    var body = self.personalize(self.context.content, {name: self.context.testname});
    self.sendMail(self.app.mailFrom, self.context.testmail, self.context.subject, body);

    finish();
  });
};



FormDataController.prototype.listData = function(finish) {
  var self = this;

  // allow users to come back to the list view and still see the same
  self.getDetailData();

  console.log("FormDataController.listData ->  meta = " + self.context.form_meta + ", status = " + self.context.form_show);

  self.query("select id, atom, data,status,created, modified from data " +
    "where (atom = ? or ? = 0) and (status = ? or ? = 'X') order by atom, created desc",
    [self.context.form_meta, self.context.form_meta, self.context.form_show, self.context.form_show], function(error, result) {
      if (error) { console.log("FormDataController.listData -> error " + error); }
      self.context.data = [];
      for (var i = 0; i < result.length; i++) {
        self.context.data[i] = cody.Meta.getData(result[i]);
      }
      finish();
    });
};


FormDataController.prototype.saveData = function(id, meta, finish) {
  var self = this;

  var atom = self.app.getAtom(meta);
  var meta = cody.FormController.makeMeta(atom);
  meta.objectId = self.getParam("id", 0);
  meta.readValuesFrom(self.context.params, false);
  meta.saveValues(self, self.getParam("status", "N"), finish);
};

FormDataController.prototype.deleteData = function(id, finish) {
  var self = this;

  self.query("delete from data where id = ?", [id], function(error, result) {
    if (error) {
      console.log("FormDataController.deleteData -> error " + error);
      self.feedBack(false, "Error deleting data [" + error + "]");
    }
    finish();

  });
};


FormDataController.prototype.editData = function(meta, id, finish) {
  var self = this;

  var atom = self.app.getAtom(meta);
  var meta = cody.FormController.makeMeta(atom);
  meta.readValues(self, id, function(error, data) {
    if (error) {
      console.log("FormDataController.editData -> error " + error);
      self.gen("NOK,Can not read the data from the database", { "Content-Type": "application/html" });
      return;
    } console.log(data);
    self.context.meta = meta;
    self.context.data = data;

    finish();
  });

};

================================================
FILE: controllers/ImageController.js
================================================
//
// Johan Coppieters - jan 2013 - jWorks
//
//
var mysql = require("mysql2");
var cody = require('../index.js');

console.log("loading " + module.id);


function ImageController(context) {
  console.log("ImageController.constructor -> page(" + context.page.itemId + ") = " +
              context.page.title + ", request = " + context.request);
  
  // init inherited controller
  cody.TreeController.call(this, context);
  
}

ImageController.prototype = Object.create( cody.TreeController.prototype );
module.exports = ImageController;



ImageController.prototype.doRequest = function( finish ) {
  var self = this;
  
  //self.context.fn = "-/cms/images.ejs";
  
  if (self.isRequest("imagelist")) {
    self.getImageList();
    finish("");

  } else {
    cody.TreeController.prototype.doRequest.call(self, finish);
    
  }
};


ImageController.prototype.getRoot = function() {
      return cody.Application.kImageRoot;
};
ImageController.prototype.getType = function(theNode) { 
  return ((theNode.extention === "xxx") || (theNode.extention === "")) ? "folder" : "image"; 
};
ImageController.prototype.getObject = function(id) {
  return this.app.getAtom(id);
};
ImageController.prototype.getFolder = function() { 
  return "/images"; 
};


/* Overridden - Action functions */


/* specific functions */
ImageController.prototype.getImageList = function() {
  console.log("Received ImageController - getImageList");

  this.gen("var tinyMCEImageList = " + this.getArray( this.getRoot() ) + ";", 
           {"Content-type": "application/javascript"}); 
  //TODO: add headers:  "pragma": "no-cache", "expires": "0" ?
};




================================================
FILE: controllers/LoginController.js
================================================
//
// Johan Coppieters - mar 2013 - cody
//
//
console.log("loading " + module.id);

var mysql = require("mysql2");
var cody = require("./../index.js");


function LoginController(context) {
  console.log("LoginController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);
  
  
	// view to be used for getting the username/password
	this.loginView = "-/login.ejs";
		
	// URL used when user logs in and no specific page/action was requested before
	this.loggedInUrl = "/" + (context.page.language || context.app.defaultlanguage) + "/dashboard";
	// URL used when the user request a log out.
	this.loggedOutUrl = "/" + (context.page.language || context.app.defaultlanguage);
		
	// use this view for the admin operations
	this.adminView = "-/cms/users.ejs";

	// init inherited controller
	cody.Controller.call(this, context);
}

LoginController.prototype = Object.create( cody.Controller.prototype );
module.exports = LoginController;


// Used to be: LoginController.prototype = new cody.Controller();
// Object.create() is an excellent choice for creating an object without going through its constructor



LoginController.prototype.doRequest = function( finish ) {
  var self = this;
  
  self.context.fn = this.adminView;
		
  if (self.isRequest("")) {
   // request for displaying the login screen
   finish( self.loginView );
		
  } else if (self.isRequest("login")) {
    // request for trying to log in with the given parameters
    self.tryLogin( finish );
 
  } else if (self.isRequest("logout")) {
    // clear login data from the session
    self.setLogin({});

    // redirect internally
    var anApp = self.app;

    var aPath = new cody.Path("/" + self.loggedOutUrl, self.app.defaultlanguage);
    var aContext = anApp.buildContext( aPath, self.context.req, self.context.res );
    anApp.handToController(aContext);    
    
  } else {
   finish();
  }
  
  return undefined;
};


LoginController.prototype.markLogin = function( theUserName, theLogin, locked, finish ) {
  // override this one if you want to log the login (= ! isActive() -> failed)
  // don't forget to call "finish"...
  
  console.log("LoginController.markLogin -> " +
    (theLogin.isActive() ? "Successfully log in for: " : locked ? "User locked: " : "Login failed for: ") +
    theUserName);
    
  finish();
};
	
LoginController.prototype.tryLogin = function( finish ) {
  var self = this;  
  var aUserName = self.getParam("username");
  var locked = false;
  
  // remove login from context and session -> there is no way back...
  self.setLogin({});
  
  cody.User.getUser(self, aUserName, this.getParam("password"), function (aUser) {
    
    console.log("login rec: " + aUserName + " - " + aUser.id + " - " + aUser.badlogins + " - " + aUser.maxbadlogins);
    if (aUser && (aUser.badlogins >= aUser.maxbadlogins)) {
      aUser.active = false;
      locked = true;
    }
   
    self.markLogin(aUserName, aUser, locked, function() {
      if (aUser.isActive()) {
        self.feedBack(true, "login-successful");
        
        // remember the user in the context and session
        self.setLogin(aUser);
        aUser.clearBadLogins(self, function() {
          self.continueRequest( finish );
        });
        
      } else {
        // failed to login, go back to the same screen
        self.feedBack(false, locked ? "login-locked" : "login-failed");
        cody.User.addBadLogin(self, aUserName, function() {
          finish(self.loginView);
        });
      }
      
    });
    
      
  });
};


LoginController.prototype.continueRequest = function(finish) {
  var self = this;
  var anApp = self.app;
  
  //check for pending request from before the login request
  var aSession = self.context.session;
  if (aSession && aSession.pendingContext) {
    console.log("LoginController.tryLogin -> found pending session after login");

    /* we could have Express handle this too, but still some research to do
      request({ url: req.host + req.path, headers: req.headers, body: req.body }, function(err, remoteResponse, remoteBody) {
            if (err) { return res.status(500).end('Error'); }
            res.writeHead(...); // copy all headers from remoteResponse
            res.end(remoteBody);
      });
    */
    
    // hand off control to pending controller and adapt our context, remove pending request
    self.context.copyFromMini(aSession.pendingContext);
    delete aSession.pendingContext;
    anApp.handToController(self.context);
    
  } else {
    // no pending request, send to "logged in" page
    console.log("LoginController.tryLogin -> found no pending session after login -> go to 'logged-in page'");

    // perhaps "loggedInUrl" in login request or take default of this controller.
    var url = self.getParam("loggedInUrl", self.loggedInUrl);

    // used to be internal redirect, now we just let the browser handle everything.
    self.redirect(url);
    finish("");
  }
};



================================================
FILE: controllers/PageController.js
================================================
//
// Johan Coppieters - jan 2013 - jWorks
//
//
var mysql = require("mysql2");
var cody = require('../index.js');

console.log("loading " + module.id);


/* One off object for making roots for Pages and Dashboard */

function Root(controller, id, name) {
  var myRoot = controller.getObject(id);
  var myChildren = myRoot.getChildren();
  
  this.getId = function() { return id; };
  this.getName = function() { return name; };
  this.hasChildren = function() { return (myChildren.length > 0); };
  this.getChildren = function() { return myChildren; };
 }
 

/* Actual PageController */

function PageController(context) {
  console.log("PageController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);
  
  // init inherited controller
  cody.TreeController.call(this, context);
}

PageController.prototype = Object.create( cody.TreeController.prototype );
// needed?  PageController.prototype.constructor = PageController;

module.exports = PageController;



PageController.prototype.doRequest = function( finish ) {
  var self = this;

  self.context.opennode = "0";
  self.context.shownode = "0";
  
  if (self.isRequest("realdelete")) {
    self.realDelete( self.getParam("node"), function whenDone(result) {
      if (result.status !== "OK") {
        self.feedBack(false, "Something went wrong during delete."); 
      }
      finish();
    });
    
    
  } else if (self.isRequest("savecontent")) {
    self.saveContent( self.getParam("node"), self.getParam("id"), finish);

    
  } else if (self.isRequest("addcontent")) {
    self.addContent( self.getParam("node"), self.getParam("kind"), function(newId) {
      finish( { status: "OK", id: newId } );
    });

    
  } else if (self.isRequest("deletecontent")) {
    self.deleteContent( self.getParam("node"), self.getParam("id"), function() {
      finish( { status: "OK" } );
    });

    
  } else if (self.isRequest("adjust")) {
    self.adjustContent( self.getParam("node"), function whenDone(result) {
      // get all info and data on this node
      finish( { status: "OK" } );
    });

  } else if (self.isRequest("SaveX")) {
    var nodeId = self.getParam("node");
    self.saveInfo( nodeId, function() {
      self.addContent(nodeId , self.getParam("kind"), function(newId) {
        self.context.opennode = cody.TreeController.toId(nodeId);
        self.context.shownode = cody.TreeController.toId(nodeId);
        finish();
      });
    });


  } else {
    self.context.shownode = cody.TreeController.toId(this.getParam("shownode", ""));
    self.context.opennode = cody.TreeController.toId(this.getParam("opennode", ""));

    // super.doRequest
    cody.TreeController.prototype.doRequest.call(self, finish);
    
  }
};



/* Overridden - Config functions */

PageController.prototype.getRoot = function() {
  return cody.Application.kHomePage;
};

PageController.prototype.getType = function(theNode) {
  return (theNode.item.showcontent === cody.Item.kContent) ? "html" : "";
};
PageController.prototype.getFolder = function() {
  return "";
};
PageController.prototype.getObject = function(id) {
  var language = this.context.page.language;  
  return this.app.getPage(language, id);
};



/* PageController utilities */

PageController.prototype.respace = function( parent, finish ) {
  var self = this;

  // Find all children, any page of the item will do, they all have the same children in any language
  var aPage = this.getObject(parent.id);

  var nr = 0;
  cody.Application.each(aPage.children, function respaceOnePage(done) {
    var aChildPage = this;
    nr += 10;
    // console.log("PageController.Respace: checking '" + aChildPage.item.name + "' now = " + aChildPage.item.sortorder + " to " + nr);
    if (aChildPage.item.sortorder !== nr) {
      aChildPage.item.sortorder = nr;
      aChildPage.item.doUpdate(self, function() {
        done();
      });
    } else {
      done();
    }

  }, function whenDone(err) {
    if (err) { console.log("PageController - respace: error = " + err); }
    if (typeof finish === "function") { finish(); }

  });

};


/* Overridden - Action functions */

PageController.prototype.addObject = function( title, refNode, type, kind, finish ) {
  var self = this;
  var show = this.getParam("showcontent", "Y");
  console.log("Received PageController - addObject, refnode = " + refNode + ", type = " + type + ", kind = " + kind+ ", show = " + show);

  var refNodeId = cody.TreeController.toId(refNode);
  var orderNr, aParent;

  // fetch the user id
  var userId = this.getLoginId();

  // fetch the parent and sortorder
  if (type === "inside") {
    orderNr = 5;
    aParent = self.app.getItem(refNodeId);
  } else {
    // after -> is always at the end -> we never get this !! (worked with previous version of jsTree)
    var refItem = self.app.getItem(refNodeId);
    orderNr = refItem.sortorder + 10;
    aParent = refItem.parent;
  }

  // can we make modifications to this parent node
  if (! self.isAllowed(aParent)) {
    finish( { status: "NAL" } );
    return;
  }

  // make the item
  var basis = cody.Item.addDefaults({name: title, user: userId, sortorder: orderNr, template: kind, showcontent: show}, aParent);
  var anItem = new cody.Item(basis, self.app);

  try {
    anItem.doUpdate(self, function() {
      // we need the id of the new item, so use the callback
      self.app.addItem(anItem);

      // make the page in all languages
      var langs = self.app.getLanguages();

      cody.Application.each( langs, function makePageForLanguage(done) {
        // iterator over all languages
        basis = cody.Page.addDefaults({language: this.id}, anItem);
        var aPage = new cody.Page(basis, self.app);

        aPage.doUpdate(self, function() {
            self.app.addPage(aPage);
            aPage.adjustContent(self, done);
        }, true);

      }, function whenDone(err) {
        // terminator

        if (err) {
          finish( { status: "NOK", error: err } );

        } else {
          finish( { status: "OK", node: "id_" + anItem.id } );
        }
      });
    });

  } catch (e) {
    console.log("PageController.AddPage: Failed to create the Item or Page objects.");
    console.log(e);
    finish( { status: "NOK", error: e } );
  }
};


PageController.prototype.moveObject = function( nodeId, refNode, type, finish ) {
  var self = this;
  // type = "before" / "after" or "last" / "inside"
  console.log("Received PageController - moveObject, refnode = " + refNode +
              ", node = " + nodeId + ", type = " + type);
  
  var orderNr;
  var aParent;
  
  // fetch the parent and insertion point
  if ((type === "inside") || (type === "last")) {
    aParent = self.app.getItem(cody.TreeController.toId(refNode));
    orderNr = 9999;
  } else {  
    var refItem = self.app.getItem(cody.TreeController.toId(refNode));
    aParent = self.app.getItem(refItem.parentId);
    orderNr = refItem.sortorder + ((type === "before") ? -5 : +5);
  }
  
  // fetch the node to be moved
  var anItem = self.app.getItem(cody.TreeController.toId(nodeId));
  var curParent = self.app.getItem(anItem.parentId);
  
  // check the new target parent
  if (! self.isAllowed(aParent)) {
    finish( { status: "NAL" } );
    return;
  }
  
  // check the current parent
  if (! self.isAllowed(curParent)) {
    finish( { status: "NAL" } );
    return;
  }

  // position in the tree
  anItem.parentId = aParent.id;
  // console.log("PageController.MovePage: old order = " + anItem.sortorder + " (of " + anItem.id + "), new order = " + orderNr);
  anItem.sortorder = orderNr;
  
  try {
    // anItem.doUpdate(self); -> done in respace too, so no need to call it here
    self.app.buildSitemap();

    self.respace(aParent, function whenDone() {
      finish( { status: "OK" } );
    });
    
  } catch (e) {
    console.log("PageController.MovePage: Failed to update the Item object.");
    console.log(e);
    finish( { status: "NOK", error: e.toString() } );
  }
};


PageController.prototype.renameObject = function( title, nodeId, finish ) {
  var self = this;
  console.log("Received PageController - renameObject, node = " + nodeId + ", title = " + title);
      
  var aPage = self.getObject( cody.TreeController.toId(nodeId) );
  if (aPage) {
      
    if (! self.isAllowed(aPage)) {
      finish( { status: "NAL" } );
      return;
    }

    aPage.title = title;
  
    try {
      aPage.doUpdate(self, function() {

        // change all names for pages from this item that still have the defaultName
        //   (the item was probably just created)
        var langs = self.app.getLanguages();
        cody.Application.each( langs, function forEachLanguage(next) {
          anotherPage = self.app.getPage(this.id, aPage.itemId);
          if (anotherPage.title === cody.Item.kDefaultName) {
            anotherPage.title = title;
            anotherPage.doUpdate(self, next);
          } else {
            next();
          }

        }, function whenDone(err) {
          // perhaps overkill but for (sortorder == alphabetical) the order of pages can change
          self.app.buildSitemap();

          // rename the item if it iss the page of the default language (although item names are not shown)
          // it's nice for debugging the database
          if ((self.app.isDefaultLanguage(aPage.language)) || (aPage.item.name === cody.Item.kDefaultName)) {
            aPage.item.name = title;
            aPage.item.doUpdate(self, function() {
              finish( { status: "OK" } );
            });
          } else {
            finish( { status: "OK" } );
          }
        });
      });
      
      
    } catch (e) {
      console.log("PageController.RenameObject: Failed to update the Page or Item object.");
      finish( {status: "NOK", error: e } );
    }
    
  } else {
    finish( {status: "NOK", error: "page not found" } );
  }
};


PageController.prototype.realDelete = function( node, finish ) {
  var self = this;
  
  console.log("Received PageController - realdelete, node = " + node);
  
  //request to delete a node from the tree
  var aPage = self.getObject( cody.TreeController.toId(node) );
  var anItem = aPage.item;
  
  // if possible, show this node after the delete
  self.context.shownode = anItem.parentId;


  if (! self.isAllowed(anItem)) {
    finish( { status: "NAL" } );
    return;
  }
  
  if (aPage.hasChildren()) {
    finish( { status: "NOE" } );
    return;
  }
  
  try {
    anItem.doDelete(self, function() {
      finish( { status: "OK" } );
    });
    
  } catch(e) {
    console.log("PageController.RealDelete: Failed to delete the Page object -- " + e);
    finish( { status: "NOK", error: e } );
  }
};


PageController.prototype.deleteObject = function( nodeId, finish ) {
  var self = this;
  
  // for pages, this function only de-activates the item
  console.log("Received PageController - deleteObject, node = " + nodeId);
  
  try {
    var aPage = self.getObject( cody.TreeController.toId(nodeId) );
    
    if (! self.isAllowed(aPage)) {
      finish( { status: "NAL" } );
      return;
    }

    aPage.doDeactivate(self, function() {
      finish( { status: "OK" } );
    });

    
  } catch (e) {
    console.log("PageController.DeletePage: Failed to delete the Page object -- " + e);
    finish( { status: "NOK", error: e } );
  }
};


PageController.prototype.fetchNode = function( theNode, finish ) {
  var self = this;
  
  var aPage = self.getObject( cody.TreeController.toId(theNode) );
  if (! self.isAllowed(aPage)) {
    this.gen("NAL,User is not allowed to edit this page with id = " + theNode, { "Content-Type": "application/html" });
    return;
  }
  
  // just switch the page in our current context and we're done ??
  self.context.page = aPage;
  
  //TODO: get all the (main) content blocks connected to this page
  // for the moment they are all there from startup
  // but then -> question? how do I get rid of all the (main) blocks -- and keep the (intro) blocks
  //  actually: "when" do I do this?
  
  console.log("PageController.FetchNode: node = " + theNode + " + language = " + aPage.language + " => " + self.context.page.item.id);
  finish();
};


PageController.prototype.saveInfo = function( nodeId, finish ) {
	var self = this;
	
  var aPage = self.getObject( cody.TreeController.toId(nodeId) );
  var anItem = aPage.item;

  anItem.scrapeFrom(self);
  anItem.doUpdate(self, function() {

    aPage.scrapeFrom(self);
    aPage.doUpdate(self, function() {

      aPage.updateContent(self, function() {

        // sortBy attributes can be changed
        self.app.buildSitemap();
        
        // signal node to be selected in the tree view
        self.context.shownode = anItem.id;
        
        finish();
      });
    });
  });
 };



/* Controller specific, called from template */

PageController.prototype.getDashboardTree = function() {
  return this.getTree( new Root(this, cody.Application.kDashboardPage, "Dashboard") );
};

PageController.prototype.getOrphansTree = function() {
  return this.getTree( new Root(this, cody.Application.kOrphansPage, "Pages") );
};


/* content stuff */

PageController.prototype.saveContent = function(thePage, theId, finish) {
  var self = this;

  var aPage = self.getObject( cody.TreeController.toId(thePage) );
  var aContentId = cody.TreeController.toId(theId);

  console.log("Received PageController - saveContent, pageId = " + thePage + ", contentId = " + aContentId);
  try {

    if (! self.isAllowed(aPage)) {
      finish( { status: "NAL" } );
      return;
    }

    var aContent;
    if (aContentId !== 0) {
      aContent = aPage.getContent(aContentId);
    } else {
      aContent = new cody.Content({}, self.app);
      aContent.attachTo(aPage, aPage.item.id, aPage.language);
    }
    aContent.scrapeFrom(self);

    aContent.doUpdate(self, (aContentId === 0), function(err) {
      if (err) {
        finish( { status: "NOK", error: err } );
      } else {
        finish( { status: "OK" } );
      }
    });


  } catch (e) {
    console.log(e);
    console.log("PageController.SaveData: failed to save the content of page " + thePage + " with id = " + theId);

    finish( { status: "NOK", error: e } );
  }
};


PageController.prototype.adjustContent = function( theNode, finish ) {
  var self = this;
  console.log("PageController.adjustContent: add correct Content for " + theNode + "");

  var aPage = self.getObject( cody.TreeController.toId(theNode) );
  aPage.adjustContent( self, function() {
    self.context.fetchnode = "id_" + aPage.itemId;
    finish();
  });
};


PageController.prototype.addContent = function( theNode, theKind, finish ) {
  var self = this;
  console.log("PageController.addContent: " + theKind + ", for " + theNode + "");
  
  var aPage = self.getObject( cody.TreeController.toId(theNode) );
  aPage.addContent( self, theKind, function(newId) {
    finish(newId);
  });
};


PageController.prototype.deleteContent = function( theNode, theId, finish ) {
  var self = this;
  console.log("PageController.deleteContent: delete content " + theId + ", for " + theNode + "");
  
  var aPage = self.getObject( cody.TreeController.toId(theNode) );
  aPage.deleteContentById(self, cody.TreeController.toId(theId), function() {
    finish();
  });
};



================================================
FILE: controllers/StylesController.js
================================================

console.log("loading " + module.id);

var mysql = require("mysql2");
var cody = require("./../index.js");
var fs = require("fs");
var path = require("path");
var util = require("util");


module.exports = StylesController;

function StylesController(context) {
    var self = this;

    console.log("StylesController.constructor");
    this.formView = "-/cms/styles.ejs";
    // init inherited controller
    cody.Controller.call(self, context);
}

StylesController.prototype = Object.create( cody.Controller.prototype );

StylesController.prototype.doRequest = function( finish ) {
    var self = this;

    self.context.fn = this.formView;

    var startupPath = path.dirname(require.main.filename);
    var projectPath = path.join(startupPath, self.context.app.name);
    var staticPath = path.join(projectPath, "static");
    var customCSSPath = path.join(staticPath, "css", "user.css");
    var imagesPath = path.join(staticPath, "images");

    var ff=imagesPath+"";

    fs.readFile(customCSSPath, 'utf8', function (err,data) {
        if (err) {
            data = "";
        }
        self.context.css = data;

        if (self.isRequest("")) {
            finish( self.formView );

        } else if (self.isRequest("newlogo")) {
            self.feedBack(true, "logo-updated");
            var uploadedFiles = self.context.req.files;
            if(uploadedFiles.logoFile === undefined){
                self.feedBack(false, "logo-none-selected");
            }   else{
                var file = uploadedFiles.logoFile;
                if(new Array("image/png").indexOf(file.type) < 0){ //TODO: add other formats but convert them
                    self.feedBack(false, "logo-unsupported-format");
                }else{
                    var destinationPath = path.join(imagesPath, "logoMC.png");
                    ins = fs.createReadStream(file.path);
                    ous = fs.createWriteStream(destinationPath);
                    util.pump(ins, ous, function(err) {
                        if(err) {
                            next(err);
                        } else {
                            res.redirect('/en/styles');
                        }
                    });
                    self.feedBack(true, "logo-updated");
                }
            }
            finish( self.formView );
        } else if (self.isRequest("newcss")) {
            var css = self.getParam("css");
            fs.writeFile(customCSSPath, css, function(err) {
                if(err) {
                    self.feedBack(false, "css-update-failed");
                } else {
                    self.feedBack(true, "css-updated");
                }
                self.context.css = css;
                finish( self.formView );
            });

        } else {
            finish();
        }
    });

    return null;
  //cody.TreeController.prototype.doRequest.call(self, finish);
};





================================================
FILE: controllers/SystemController.js
================================================

console.log("loading " + module.id);

var mysql = require("mysql2");
var cody = require("./../index.js");
var fs = require("fs");
var path = require("path");
var util = require("util");

var mysql = require("mysql2");

module.exports = SystemController;

function SystemController(context) {
    var self = this;

  console.log("SystemController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);

    // init inherited controller
    cody.Controller.call(self, context);
}
SystemController.prototype = Object.create( cody.Controller.prototype );


//fetch config values from database
SystemController.prototype.doRequest = function( finish ) {
  var self = this;
  self.context.fn = "-/cms/system.ejs";

  if (self.isRequest("reload")) {
    self.app.init(function() {
      self.feedback(true, "System reloaded.");
      finish();
    });

  } else if (self.isRequest("Save")) {
    self.query("UPDATE cody.websites SET hostname=? WHERE id=?", [this.getParam("hostname"), this.getParam("id")], function (err2, results2) {
      self.doList(function() {
        self.app.init(function() {
          self.feedback(true, "Parameters saved and system reloaded.");
          finish();
        });
      });
    });

  } else if (self.isRequest("Hosting")) {
    self.doList(finish);

  } else {
    finish();
  }

};

SystemController.prototype.doList = function(finish) {
  var self = this;

  var hostname = self.context.req.headers.host;
  if (hostname.indexOf(":") >= 0) {
    hostname = (hostname.split(":"))[0];
  }
  var hostnameA = self.escape("%," + hostname);
  var hostnameB = self.escape(hostname + ",%");
  hostname = self.escape(hostname);

  self.query("SELECT * FROM cody.websites WHERE hostname=" + hostname + " OR hostname LIKE " + hostnameA + " OR hostname LIKE " + hostnameB, function (err, results) {
    if (err) throw err;
    if (results.length > 0) {
      var result = results[0];
      self.context.config = result;
      finish(self.formView);
    }
  });
};


================================================
FILE: controllers/TemplateController.js
================================================
//
// Johan Coppieters - may 2013 - cody
//
//
console.log("loading " + module.id);

var mysql = require("mysql2");
var cody = require("../index.js");


function TemplateController(context) {
  console.log("TemplateController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);

  // init inherited controller
  cody.Controller.call(this, context);
}

TemplateController.prototype = Object.create( cody.Controller.prototype );
module.exports = TemplateController;



TemplateController.prototype.doRequest = function( finish ) {
  var self = this;
  var thisId = this.getInt("id", -1);

  // request for displaying the login screen
  if (self.isRequest("") || this.isRequest("list")) {
    self.doList( finish );

  } else if (self.isRequest("save")) {
    self.doSave( thisId, function() {
      self.setRequest("list");
      self.doList( finish );
    });

  } else if (self.isRequest("duplicate")) {
    self.doDuplicate( thisId, function(newId) {
      self.doGet( newId, finish);
    });

  } else if (self.isRequest("delete")) {
    self.doDelete( thisId, function() {
      self.setRequest("list");
      self.doList( finish );
    });

  } else if (this.isRequest("edit")) {
    self.doGet( thisId, finish);

  } else if (this.isRequest("new")) {
    self.doGet( NaN, finish );


  } else if (self.isRequest("addcontent")) {
    self.doAddContent( thisId, self.getParam("content", "S"), function() {
      self.doGet( thisId, finish);
    });

  } else if (self.isRequest("delcontent")) {
    self.doDelContent( thisId, self.getParam("content", 0), function() {
      self.doGet( thisId, finish);
    });

  } else {
    finish();
  }

  return undefined;
};



TemplateController.prototype.doDelete = function( theId, finish ) {
  var self = this;

  if (self.app.templateUsed(theId)) {
    self.feedBack(false, "Failed to delete the template, it is still in use by some pages");
    finish();
    return;
  }

  var aTemplate = this.app.deleteTemplate(theId);
  if (typeof aTemplate !== "undefined") {
    aTemplate.doDelete(self, function() {
      aTemplate.deleteAllContent(self, function() {
        self.feedBack(true, "Successfully deleted the template and its content");
        finish();
      });
    });
  } else {
    self.feedBack(false, "Failed to delete the template, it was not found");
    finish();
  }
};


TemplateController.prototype.doSave = function( theId, finish ) {
  var self = this;
  var aTemplate = self.app.getTemplate(theId);
  if (typeof aTemplate === "undefined") {
    aTemplate = new cody.Template({id: 0}, self.app.controllers);
  }
  aTemplate.scrapeFrom(self);
  aTemplate.doUpdate(self, function() {
    aTemplate.updateContent(self, function() {
      self.feedBack(true, "Successfully saved the template and its content");
      finish();
    });
  });
};


TemplateController.prototype.doDuplicate = function( theId, finish ) {
  var self = this;
  var aTemplate = self.app.getTemplate(theId);
  var newTemplate = new cody.Template(aTemplate, self.app.controllers);
  newTemplate.id = 0; // mark as new

  newTemplate.scrapeFrom(self);
  if (newTemplate.name === aTemplate.name) {
    newTemplate.name = newTemplate.name + " copy";
  }

  // create the template in the database
  newTemplate.doUpdate(self, function() {

    // duplicate content blocks
    newTemplate.copyContentFrom(self, theId, function() {

      self.feedBack(true, "Successfully duplicated the template");
      finish(newTemplate.id);
    });
  });
};

TemplateController.prototype.doGet = function(id, finish) {
  var self = this;
  var aTemplate;

  // get or make the template object
  if ((typeof id === "undefined") || isNaN(id) || (id === 0)) {
    aTemplate = new cody.Template({id: 0}, self.app.controllers);

    // store it in the context for our view
    self.context.template = aTemplate;

    // terminate -> new template is ready for editing
    finish();

  } else {
    aTemplate = self.app.getTemplate(id);

    // store it in the context for our view
    self.context.template = aTemplate;

    // attach all its content objects
    aTemplate.fetchContent(self.app, id, finish);
  }
};


TemplateController.prototype.doList = function(finish) {
  var self = this;
  self.context.templates = self.app.templates;

  finish();
};


///////////////////
// Content Stuff //
///////////////////

TemplateController.prototype.doAddContent = function( theId, kind, finish ) {
  var self = this;
  var aTemplate = self.app.getTemplate(theId);
  aTemplate.addContent(self, theId, kind, function() {
    self.feedBack(true, "Successfully added content to the template");
    finish();
  });
};

TemplateController.prototype.doDelContent = function( theId, theContent, finish ) {
  var self = this;
  var aTemplate = self.app.getTemplate(theId);
  aTemplate.deleteContent(self, theContent, function() {
    self.feedBack(true, "Successfully deleted content to the template");
    finish();
  });
};




================================================
FILE: controllers/TreeController.js
================================================
  
//
// Johan Coppieters - mar 2013 - cody
//
//
console.log("loading " + module.id);

var mysql = require("mysql2");
var fs = require("fs");
var cody = require('../index.js');


function TreeController(context) {
  console.log("TreeController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);
  
  // init inherited controller
  cody.Controller.call(this, context);

  context.shownode = this.getRoot();
}

TreeController.prototype = Object.create( cody.Controller.prototype );
module.exports = TreeController;


TreeController.prototype.getFilePath = function() { 
  return this.context.dynamic + this.getFolder(); 
};

// Next 4 should be overridden
TreeController.prototype.getRoot = function() { 
  throw new Error("TreeController.getRoot should be overridden - return an id");
};
TreeController.prototype.getType = function(theNode) { 
  throw new Error("TreeController.getType should be overridden - return a string (image, folder, ...) to be used by the Atom tree to display the nodes");
};
TreeController.prototype.getObject = function(id) {
  throw new Error("TreeController.getObject should be overridden - return an Atom with the specified id");
};
TreeController.prototype.getFolder = function() { 
  throw new Error("TreeController.getFolder should be overridden - return a string / subpath in which the documents can be found");
};


/* required protocol for nodes:
Node.prototype.getAllowedDomains = function() { return ""; }
Node.prototype.hasChildren = function() { return false; }
Node.prototype.isActive = function() { return true; }
Node.prototype.isVisible = function() { return true; }
Node.prototype.getChildren = function() { return []; }
Node.prototype.getSortOrder = function() {}
Node.prototype.setSortOrder = function(nr) {}
Node.prototype.setName = function(name) {}
Node.prototype.getName = function() {}
Node.prototype.getId = function() {}

Node.prototype.scrapeFrom = function(controller) {}
Node.prototype.doUpdate = function(controller, finish) {}
Node.prototype.doDelete = function(controller, finish) {}
*/
      

TreeController.toId = function(theNode) {
  if ((typeof theNode === "undefined") || (theNode === "")) {
    return 0;
  } else if (theNode.indexOf("id_") === 0) {
    return parseInt(theNode.substring(3), 10);
  } else {
    return parseInt(theNode, 10);
  }
};


TreeController.prototype.doRequest = function( finish ) {
  var self = this;

  if (self.isRequest("insert")) {
    // a new node was inserted in the tree
    self.addObject( self.getParam("name"), 
                    self.getParam("refnode"),
                    self.getParam("type"),
                    self.getParam("kind"), finish );
    
    
  } else if (self.isRequest("move")) {
    // a  node was being moved around in the tree
    this.moveObject( self.getParam("node"), 
                     self.getParam("refnode"),
                     self.getParam("type"), finish);
    
    
  } else if (self.isRequest("rename")) {
    // a node has been renamed in the tree
    this.renameObject( self.getParam("name"),  
                       self.getParam("node"), finish);
        
    
  } else if (self.isRequest("realdelete")) {
    // request to really delete a node from the tree
    this.realDeleteObject( self.getParam("node"), finish);

    
  } else if (self.isRequest("delete")) {
    // request to mark a node as "deleted" / "inactive" in the tree
    this.deleteObject( self.getParam("node"), finish);

    
  } else if (self.isRequest("select")) {
    // generate a input/type=select
    this.gen( this.getList() );
    finish("");
       
  } else if (self.isRequest("menu")) {
    // generate a ul/li tree for menus
    this.gen( this.getMenu(), { "Content-Type": "application/html" } );
    finish("");
       
    
  } else if (self.isRequest("getnode")) {
    // get all info and data on this node
    this.fetchNode( self.getParam("node"), function() {
      finish( self.context.fn.replace(".ejs", "-ajax.ejs") );
    });
        
    
  } else if (self.isRequest("save")) {
    // save all info on this node (done by a submit, so we need to redraw the screen, too bad)
    this.saveInfo( self.getParam("node"), finish );

    
  } else {
    // no specific request, just draw the tree...
    finish();
  }
};


//display the complete tree to be used in a array with id / filename.
TreeController.prototype.getArray = function( theRoot ) {
  var self = this;
  var imagePath = self.getFilePath();
  var aRoot = self.getObject((typeof theRoot === "undefined") ? this.getRoot() : theRoot);

  function dashes(cnt) { 
    var s = ""; 
    for (var i=0; i<cnt; i++) { s += "-"; } 
    return s; 
  }

  function renderArray( theNode, level ) {
    var aTree = "";
    var aList = theNode.getChildren();
    for (var x in aList) { 
      var p = aList[x];
      if (p.isVisible()) {
        if (aTree.length > 0) { aTree += ", "; }
        aTree += "[\"" + dashes(level) + " " + p.getName() + "\",\"" + imagePath + "/" + p.getFileName() + "\"]";
        var rest = renderArray(p, level+1);
        if (rest.length > 0) { aTree += "," + rest; }
      }
    }
    return aTree;
  }
  return "[" + renderArray( aRoot, 0 ) + "]";
};
  
    
//display the complete tree to be used in a select/menu.
TreeController.prototype.getMenu = function( theRoot ) {
  var self = this;
  var aRoot = (typeof theRoot === "object") ? theRoot : self.getObject((typeof theRoot === "undefined") ? self.getRoot() : theRoot);
  
  function renderTree( theNode ) {
    var aTree = "";
    var aList = theNode.getChildren();
    for (var x in aList) { 
      var p = aList[x];
      if (p.isVisible()) {
        aTree += "<li id=\"" + p.id + "\" rel=\"" + p.getFileName() + "\" title=\"" + p.name +"." + p.extention + "\"><a href=\"#\">" + p.getName() + "</a>" + renderTree(p) + "</li>";
      }
    }
    return (aTree.length === 0) ? "" :  "<ul>" + aTree + "</ul>";
  }
  return renderTree( aRoot );
};
  
    
//display the complete tree to be used in a select/menu.
TreeController.prototype.getList = function( theRoot ) {
  var self = this;
  var aRoot = (typeof theRoot === "object") ? theRoot : self.getObject((typeof theRoot === "undefined") ? self.getRoot() : theRoot);
  
  function renderTree( theNode ) {
    var aTree = "";
    var aList = theNode.getChildren();
    for (var x in aList) { 
      var p = aList[x];
      if (p.isVisible()) {
        aTree += "<li id=\"" + p.getId() + "\" rel=\"" + p.getFileName() + "\">" +
                 p.getName() + renderTree(p) + "</li>";
      }
    }
    return (aTree.length === 0) ? "" :  "<ul>" + aTree + "</ul>";
  }
  
  return renderTree( aRoot );
};
  
    


// The complete tree for the admin part of the essen
TreeController.prototype.getTree = function( theRoot ) {
  var self = this;
  var aRoot = (typeof theRoot === "number") ? self.app.getAtom(theRoot) :
              (typeof theRoot === "object") ? theRoot :
              self.getObject((typeof theRoot === "undefined") ? self.getRoot() : theRoot);
  
  function renderTree( theNode, open, descend ) {
    var aTree = "";
    if (typeof theNode != "undefined") {
      var aList = theNode.getChildren();
      for (var x in aList) { var p = aList[x];
         var name = (p.isActive()) ? p.getName() : "("+p.getName()+")";
         var classes = (open ? "open " : "") +
                       (p.isVisible() ? "" : "invisible ") +
                       (p.isActive() ? "" : "deleted");
           aTree += "<li id=\"id_" + p.getId() + "\" class=\"" + classes + "\"" +
                 " rel=\""+ self.getType(p) + "\"" +
                "><a href=\"#\">" + name + "</a>";
           if (descend > 0) {
             aTree += renderTree(p, false, descend-1);
           }
           aTree += "</li>";
      }
    }
    if (aTree.length === 0) {
       return "";
    } else {
       return "<ul>" + aTree + "</ul>";
    }
  }

  return renderTree( aRoot, false, 99 );
};
  


TreeController.prototype.saveInfo = function( nodeId, finish ) {
  var self = this;
  console.log("FormController.saveInfo: node = " + nodeId );
  
  var anObject = this.getObject(TreeController.toId(nodeId));
  if (typeof anObject !== "undefined") {
     self.context.shownode = anObject.parentId;
     anObject.scrapeFrom(this);
      var F = self.context.req.files;
      
      if ((typeof F !== "undefined") && (typeof F.fileToUpload !== "undefined")) {
        F = F.fileToUpload;
       
        if (F.size !== 0) {
          // find the name of the file 
          var dot = F.name.lastIndexOf(".");
          anObject.setExtention(F.name.substring(dot+1));
          var oldNote = anObject.getNote() || "";
          if (oldNote === "") { anObject.setNote(F.name.substring(0, dot)); }
          var newPath = anObject.getPathName(self);
          
          // move the tmp file to our own datastore 
          console.log("TreeController.saveInfo: moving file from " + F.path + " to " + newPath);
          fs.rename(F.path, newPath, function(err) {
            if (err) {
              console.log(err);
              this.feedBack(false, "unable to rename uploaded file to " + newPath);
            } else {
              anObject.doUpdate(self, finish);
            }
          });
        } else {
          // just delete the tmp file if it's empty
          fs.unlink(F.path, function() {
            anObject.doUpdate(self, finish);
          });
        }
        
      } else {
        console.log("TreeController.saveInfo: no file attached.");
        anObject.doUpdate(self, finish);
      }

  } else {
    this.feedBack(false, "failed to save the data");
    finish();
  }
};


TreeController.prototype.addObject = function( title, refNode, type, kind, finish ) {
  var self = this;
  console.log("Received TreeController - addObject, refnode = " + refNode + ", title = " + title + ", type = " + type + ", kind = " + kind);
  
  var refNodeId = TreeController.toId(refNode);
  var orderNr, aParent;
  var ext = (kind === "folder") ? "xxx" : (kind === "form") ? "" : "---";

  // fetch the parent and sortorder
  if (type === "inside") {
    orderNr = 5;
    aParent = self.app.getAtom(refNodeId);
  } else { 
    // after -> is always at the end -> we never get this !! (worked with previous version of jsTree)
    var refItem = self.app.getAtom(refNodeId);
    orderNr = refItem.sortorder + 10;
    aParent = refItem.parent;
  }

  var basis = cody.Atom.addDefaults({name: title, sortorder: orderNr, extention: ext}, aParent);
  var anAtom = new cody.Atom(basis);
  anAtom.pickParent(self.app.atoms);
  
  // console.log(anAtom);

  anAtom.doUpdate(self, function() {
    self.app.addAtom(anAtom);
    finish( { status: "OK", node: "id_" + anAtom.id } );
  });
  
};

TreeController.prototype.moveObject = function( nodeId, refNode, type, finish ) {
  var self = this;
  // type = "before" / "after" or "last" / "inside"
  console.log("Received TreeController - moveObject, refnode = " + refNode +
    ", node = " + nodeId + ", type = " + type);

  var orderNr;
  var aParent;

  // fetch the parent and insertion point
  if ((type === "inside") || (type === "last")) {
    aParent = self.app.getAtom(cody.TreeController.toId(refNode));
    orderNr = 9999;
  } else {
    var refItem = self.app.getAtom(cody.TreeController.toId(refNode));
    aParent = self.app.getAtom(refItem.parentId);
    orderNr = refItem.sortorder + ((type === "before") ? -5 : +5);
  }

  // fetch the node to be moved
  var anItem = self.app.getAtom(cody.TreeController.toId(nodeId));
  var curParent = self.app.getAtom(anItem.parentId);

  // position in the tree
  anItem.parentId = aParent.id;
  //console.log("TreeController.MovePage: old order = " + anItem.sortorder + " (of " + anItem.id + "), new order = " + orderNr + ", in parent = " + anItem.parentId);
  anItem.sortorder = orderNr;

  try {
    self.respace(aParent, function whenDone() {
      finish( { status: "OK" } );
    });

  } catch (e) {
    console.log("TreeController.MoveItem: Failed to update the Item object.");
    console.log(e);
    finish( { status: "NOK", error: e.toString() } );
  }
};

TreeController.prototype.renameObject = function( title, nodeId, finish ) {
  var self = this;
  console.log("Received TreeController - rename, node = " + nodeId + ", title = " + title);
  
  var anObject = this.getObject(TreeController.toId(nodeId));
  if (typeof anObject !== "undefined") {
    try {
      anObject.setName(title);
      anObject.doUpdate(self, function() {
        self.context.shownode = anObject.id;
        finish( { status: "OK" } );
      });
      
    } catch (e) {
      console.log("TreeController.RenameObject: Failed to update the object - " + e);      
      finish( { status: "NOK", error: e.toString() } );
    }
  } else {
    finish( { status: "NOK"} );
  }
};

TreeController.prototype.deleteObject = function( nodeId, finish ) {
  var self = this;
  var anObject = self.getObject(TreeController.toId(nodeId));
  if (self.app.hasAtomChildren(anObject)) {
    finish({ status: "NOE", error: "not empty"});
    
  } else {
    self.context.shownode = anObject.parentId;
    anObject.doDelete(self, function(err) {
      if (err) {
        finish({status: "NOK", error: err.toString()});    
      } else {
        finish({status: "OK"});    
      }
    });
  }
};
TreeController.prototype.realDeleteObject = function( nodeId, finish ) {
  var self = this;
  this.deleteObject( nodeId, function(msg) {
    if (msg.status === "NOE") {
      self.feedBack(false, "There are still elements below this item");
      finish();
      
    } else if (msg.status === "NOK") {
      self.feedBack(false, "Error deleting this item: " + msg.error);
      finish();   
      
    } else {
      self.feedBack(true, "Item successfully deleted");
      finish();    
      
    }
  });
};


TreeController.prototype.makeSelect = function( type ) {
};


TreeController.prototype.fetchNode = function( nodeId, finish ) {
  console.log("TreeController.FetchNode: nodeId = " + nodeId);
  this.context.atom = this.getObject(TreeController.toId(nodeId));
  if (! this.context.atom) {
    this.gen("NOK,Could not find the requested atom with id = " + nodeId, { "Content-Type": "application/html" });
  } else {
    finish();
  }
};


TreeController.prototype.respace = function( parent, finish ) {
  var self = this;

  var aList = parent.getChildren();

  var nr = 0;
  cody.Application.each(aList, function respaceOnePage(done) {
    var aChild = this;
    nr += 10;
    //console.log("TreeController.Respace: checking '" + aChild.name + "' now = " + aChild.sortorder + " to " + nr);
    if (aChild.getSortOrder() !== nr) {
      aChild.setSortOrder(nr);
      aChild.doUpdate(self, function() {
        done();
      });
    } else {
      done();
    }

  }, function whenDone(err) {
    if (err) { console.log("TreeController - respace: error = " + err); }
    if (typeof finish === "function") { finish(); }

  });

};


================================================
FILE: controllers/UserController.js
================================================
//
// Johan Coppieters - mar 2013 - cody
//
//
console.log("loading " + module.id);

var mysql = require("mysql2");
var cody = require("./../index.js");


function UserController(context) {
  console.log("UserController.constructor -> page(" + context.page.itemId + ") = " + context.page.title + ", request = " + context.request);

	// init inherited controller
	cody.Controller.call(this, context);
}

UserController.prototype = Object.create( cody.Controller.prototype );
module.exports = UserController;


UserController.prototype.doRequest = function( finish ) {
  var self = this;


  if (self.isRequest("") || this.isRequest("list")) {
    self.doList( finish );

  } else if (self.isRequest("save")) {
      self.doSave(  this.getId(), function() {
        self.nextRequest("list", finish);
      });

  } else if (self.isRequest("delete")) {
      self.doDelete( this.getId(), function() {
        self.nextRequest("list", finish);
      });

  } else if (this.isRequest("edit")) {
    self.doGet( this.getId(), finish);

  } else if (this.isRequest("new")) {
    self.doGet(NaN, finish);

  } else {
    cody.Controller.prototype.doRequest.call(this, finish);
  }
};



UserController.prototype.doDelete = function( theId, finish ) {
  var self = this;
  
  cody.User.deleteUser(self, theId, function(isOK) {
    if (isOK) {
      self.feedBack(true, "Successfully deleted the user");
    } else {
      self.feedBack(false, "Failed to delete the user");
    }
    finish();
  });
};

	
UserController.prototype.doSave = function( theId, finish ) {
  var self = this;
  cody.User.getUser( self, theId, function(aUser) {
    aUser.scrapeFrom(self);
    aUser.doUpdate(self, function() {
      if (aUser.id === self.getLoginId()) {
        self.setLogin(aUser);
      }
      self.feedBack(true, "Successfully saved the user");
      finish();
    });    
  });
};


UserController.prototype.doGet = function(id, finish) {
  var self = this;
  
  self.doGetRefs( function() {
    if (isNaN(id) || (id <= 0)) {
      self.context.user = new cody.User({id: 0});
      finish();
    } else {
      cody.User.getUser( self, id, function(record) {
        self.context.user = record;
        finish();
      });
    }
  });
};


UserController.prototype.doGetRefs = function(finish) {
  var self = this;
  
  cody.User.getDomains( self, function(list) {
    // also update the list which is kept in the Application object
    self.app.storeDomains(list);
    self.context.domains = self.app.domains;
    
    cody.User.getLevels( self, self.getLoginLevel(), function(list) {
      self.context.levels = list;
      
      finish();
    });
  });
};

UserController.prototype.doList = function(finish) {
  var self = this;
  cody.User.getUsers(self, self.getLoginLevel(), function(list) {
    self.context.users = list;
    
    self.doGetRefs(finish);
  });
};



================================================
FILE: doc/Context.txt
================================================
//
// Johan Coppieters - jan 2013 - Cody
//
//
//
// Context
//
// Created by Application in buildContext as results of servePage for every request,
// containing all the context info for that request.
//
// Accessible
//    - through the controller of the request
//    - used as global scope while rendering a view
//      so all its properties are accessible as globals for the view rendered for that request.
//
// Additionally provides some helpers (formatting/utitlities), thus accessible by the views.

//
// Instance variables
//

// from the constructor"

function Context(path, page, app, req, res) {

  this.version = [ string ]     // copied from incoming Application object

  this.page = page;
  this.app = app;
  this.req = req;
  this.res = res;
  this.path = path;
  this.params = [ hashmap<string, string> ]      // sum of url params + if available all posted values <name, value>
  this.request = [ string ]      //

  this.status = [ string ]       // "success", "failed"
  this.message = [ string ]      // corresponding message

  this.host = [ string ]         // copied from: req.headers.host  =  name for the (virtual) host
  this.dateFormat = [ string ];  //  "dd-mm-yyyy" / "yyyy-mm-dd" / "dmm-dd-yyyy"

  this.min = [ string ]          // "" / ".min" to be used when including scripts minified of not
  this.static = [ string ];      // path to all static content, example: in a view: <%= static %>/aLayout.css
  this.dynamic = [ string ];     // path to all dynamic content, example: in a view: <%= dynamic %>/images/123.jpg
  this.cstatic = [ string ];     // path to all static content of the framework, example: in a view: <%= cstatic %>/icons/P.png

  this.strings = [ hashmap<string, string> ]  // all content of the page "[language]/strings", typically to be used as application wide multi language labels

  this.fn = [ string ]           // the name of the view file of the current page, if nothing specified: "index.ejs";

  this.session [ session object ] // copied from the request-object, if available this session also contains the login user-object
  this.cody = [ cody module ]    // making the complete cody lib accessible to your controller and/or views


--------------------------------------------------------------------------------------------------------------------


Context.prototype.render = function(params)
//
// Render content queried by name or kind.
//

// params:
//
// { kind:     String,
//   not_kind: String,
//   name:     String,
//   not_name: String,
//   intro:    Y/N,         Show intro part?
//   page:     Page }       Optional Page to get the content from instead of current

--------------------------------------------------------------------------------------------------------------------


//
// login stuff
//

Context.prototype.setLogin = function(login) {
  this.session.login = login;
  this.login = new cody.User(login);
};
Context.prototype.isLoggedIn = function() {
  return (this.login) && (typeof this.login !== "undefined") && (this.login.active === "Y");
};
Context.prototype.getLogin = function() {
  return this.login || new cody.User({});
};

--------------------------------------------------------------------------------------------------------------------

//
// General utilities
//
Context.prototype.getValueByIndex = function(object, index) {
  var nr = 0;
  for (var iO in object) {
    if (nr === index) { return object[iO]; }
    nr++;
  }
  return undefined;
}
Context.prototype.getKeyByIndex = function(object, index) {
  var nr = 0;
  for (var iO in object) {
    if (nr === index) { return iO; }
    nr++;
  }
  return undefined;
}

--------------------------------------------------------------------------------------------------------------------

Context.prototype.val = function(value) {
  return (typeof value === "undefined") ? "" : value;
};

Context.prototype.getUnique = function() {
  return new Date().getTime();
};



--------------------------------------------------------------------------------------------------------------------
rendering widgets
--------------------------------------------------------------------------------------------------------------------

// returns 'checked' if true, for option lists.
Context.prototype.checked = function( bool ) {
  return (bool) ? 'checked' : '';
};

//
// Creates html options from a given list
//
// 1. optionList([String], String)
//    Creates an option for each string and marks theId as string.

// 2. optionList([Object], String, String, String)
//    Creates an option for each object, using theIdName and theNameName properties
//    of each object to set the id and html resp.
//
Context.prototype.optionList = function(theList, theId, theIdName, theNameName) {
  var x = "";
  var first = cody.Application.findFirst(theList);

  if (typeof first === "string") {
    for (var j=0; j < theList.length; j++) {
      var S = theList[j];
      x += "<option value=\"" + S + "\"" + ((S == theId) ? "selected" : "") + ">" + S + "</option>\n";
    }

  } else {
    var idName = theIdName || "id";
    var nameName = theNameName || "name";

    for (var i in theList) {
      if (theList.hasOwnProperty(i)) {
        var O = theList[i];
        x += "<option value=\"" + O[idName] + "\"" + ((O[idName] == theId) ? "selected" : "") + ">" + O[nameName] + "</option>\n";
      }
    }
  }
  return x;
};

//
// optionListF([Any], String, (Any) -> String, (Any) -> String) -> String
//
//    Uses two functions that take an element from the list as argument and return
//    an id/name to create the options. Marks the option that has the id theId as "selected".
//
Context.prototype.optionListF = function (theList, theId, getId, getName) {
  var options = "";
  theList.forEach(function (item) {
    var id = getId(item);
    console.log(id);
    var name = getName(item);
    options += "<option value=\"" + id + "\"" + ((id == theId) ? "selected" : "") + ">" + name + "</option>\n";
  });
  return options;
};


Context.prototype.find = function(theList, theId, theIdName) {
  var idName = theIdName || "id";
  for (var i=0; i < theList.length; i++) {
    var R = theList[i];
    if (R[idName] == theId) {
      return R;
    }
  }
  return {};
};


//
// Session handlers
//

Context.prototype.fromSession = function(paramName, defaultValue) {
  var x = this.session[paramName];
  return (typeof x === "undefined") ? defaultValue : x;
};

Context.prototype.toSession = function(paramName, value) {
  this.session[paramName] = value;
};


//
// Request Parameter handlers
//

Context.prototype.getParam = function(paramName, defaultValue) {
  var x = this.params[paramName];
  return (typeof x === "undefined") ? defaultValue : x;
};

Context.prototype.setParam = function(paramName, value) {
  this.params[paramName] = value;
};



function two(n)

// Adds a leading "0" when the number < 10.


Context.prototype.formatTime = function(aDate)

// returns the time formated as "HH:MM:SS"


Context.prototype.formatShortTime = function(aDate)

// returns the time formated as "HH:MM"



//
//  format depending on the dateFormat field of this context
//
Context.prototype.formatDate = function(aDate) {

Context.prototype.makeDate = function(value, defaultValue) {

Context.prototype.makeInt = function(value, defaultValue) {

Context.prototype.makeNum = function(value, defaultValue, precision) {



================================================
FILE: doc/empty/controllers/YourController.js
================================================
console.log("loading " + module.id);
var cody = require("cody");


function YourController(context) {

    // init inherited Controller
    cody.Controller.call(this, context);
}
YourController.prototype = Object.create(cody.Controller.prototype);


YourController.prototype.doRequest = function( finish ) {
    var self = this;

    // 1) do the necessary model operations

    // 2) return a result:
    //
    // a) render the attached view of this controller
    finish();

    // b) render the view with given path:
    // finish('views/yourview.ejs')

    // c) if you don't want any rendering to be done:
    //  pass an empty string (or set this.context.fn to empty)
    // finish('')

    // d) return json:
    // finish({foo: 'bar'});

    // e) you can let the super controller handle the request
    // cody.Controller.prototype.doRequest.call(self, finish);

    // more...
};

module.exports = YourController;

================================================
FILE: doc/empty/empty.sql
================================================
SET sql_mode = 'STRICT_TRANS_TABLES';

CREATE FUNCTION PASSWORD2(s VARCHAR(50))
     RETURNS VARCHAR(50) DETERMINISTIC
     RETURN CONCAT('*', UPPER(SHA1(UNHEX(SHA1(s)))));
     
DROP TABLE IF EXISTS `atoms`;

CREATE TABLE `atoms` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent` int(11) NOT NULL DEFAULT '0',
  `sortorder` int(11) DEFAULT '0',
  `name` varchar(64) NOT NULL DEFAULT '',
  `note` varchar(4096) DEFAULT NULL,
  `extention` varchar(4) DEFAULT '',
  `created` datetime DEFAULT '0000-00-00 00:00:00',
  `updated` datetime DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`)
) AUTO_INCREMENT=200 DEFAULT CHARSET=utf8;

LOCK TABLES `atoms` WRITE;
INSERT INTO `atoms` VALUES 
(1,0,10,'Images','','','2012-01-01 00:00:00','2013-11-02 18:28:10'),
(2,0,20,'Files','','','2012-07-09 14:18:36','2012-07-09 14:18:36'),
(3,0,20,'Forms','','','2012-07-09 14:18:36','2012-07-09 14:18:36'),
(4,0,10,'Layout','','','2010-01-01 00:00:00','2010-01-01 00:00:00'),

(11,4,10,'Logo','ourlogo','png','2010-01-01 00:00:00','2013-11-02 18:15:35'),
(12,4,10,'Header','','---','2010-01-01 00:00:00','2010-01-01 00:00:00'),
(13,4,10,'Footer','','---','2010-01-01 00:00:00','2010-01-01 00:00:00'),

(21,1,10,'General','','','2012-08-15 18:55:51','2014-09-03 10:24:30'),

(32,3,5,'Contact Formulier','{\"name\":\"Contact Formulier\",\"labels\":{\"en\":\"Send\",\"it\":\"Send\"},\"alert\":\"nobody@mysite.com\"}','','2013-09-07 22:03:12','2014-09-03 10:26:15'),
(33,32,10,'name','{\"name\":\"name\",\"labels\":{\"en\":\"Name\",\"it\":\"Name\"},\"generator\":1,\"options\":{\"required\":true},\"reader\":1}','---','2013-09-07 22:32:45','2014-09-03 10:27:20'),
(35,32,30,'question','{\"name\":\"question\",\"labels\":{\"en\":\"Question\",\"it\":\"Question\"},\"generator\":2,\"options\":{\"required\":true,\"cols\":\"60\",\"rows\":\"6\"},\"reader\":1}','---','2013-09-08 11:24:14','2014-09-03 10:27:10'),
(36,32,20,'e-mail address','{\"name\":\"e-mail address\",\"labels\":{\"en\":\"Email Address\",\"it\":\"Email Address\"},\"generator\":1,\"options\":{\"required\":true,\"email\":true},\"reader\":2}','---','2013-09-08 15:59:32','2014-09-03 10:26:57'),
(37,2,20,'A File','My PDF - 23 mei 2013','pdf','2013-09-08 16:04:49','2014-09-03 10:28:39'),

(40,1,5,'Photos','','xxx','2013-09-09 15:41:08','2014-09-03 10:24:24'),
(41,40,5,'Photo1','Screen Shot 2013-09-09 at 15.40.35','jpg','2013-09-09 15:41:18','2014-09-03 10:24:39'),
(42,40,5,'Photo2','Screen Shot 2013-09-09 at 15.42.56','JPG','2013-09-09 15:43:48','2014-09-03 10:24:48'),
(43,21,10,'Image1','image','jpg','2013-09-09 16:01:56','2014-09-03 10:25:04'),
(44,2,10,'Official Documents','','xxx','2013-09-09 16:03:05','2014-09-03 10:25:29'),
(45,44,5,'Founded','Founded on april 1rst 1984','pdf','2013-09-09 16:03:16','2014-09-03 10:29:45'),
(49,21,20,'Image2','ourimage','jpg','2013-09-30 20:23:34','2014-09-03 10:25:08'),
(50,21,30,'Image3','diversity','jpg','2013-09-30 20:26:34','2014-09-03 10:25:12');
UNLOCK TABLES;

DROP TABLE IF EXISTS `content`;
CREATE TABLE `content` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `item` int(11) NOT NULL DEFAULT '0',
  `language` varchar(2) NOT NULL DEFAULT 'nl',
  `sortorder` int(11) DEFAULT '0',
  `intro` char(1) NOT NULL DEFAULT 'N',
  `kind` char(1) NOT NULL DEFAULT 'T',
  `atom` int(11) DEFAULT '0',
  `name` varchar(32) NOT NULL DEFAULT '',
  `data` text NOT NULL,
  PRIMARY KEY (`id`),
  KEY `item` (`item`,`language`)
) AUTO_INCREMENT=200 DEFAULT CHARSET=utf8;


LOCK TABLES `content` WRITE;
INSERT INTO `content` VALUES 
(1,97,'nl',10,'N','T',0,'','<p><span>Cody draagt zorg voor uw privacy. Lees deze Privacyverklaring om meer te weten te komen over de manier waarop persoonsgegevens worden ingezameld en verwerkt op deze website. In dit geval handelt Cody Howest daarbij steeds in overeenstemming met de bepalingen van de Belgische privacywet (Wet van 8 december 1992 tot bescherming van de persoonlijke levenssfeer ten opzichte van de verwerking van persoonsgegevens). De persoonlijke gegevens beperken zich enkel tot uw e-mailadres.</span></p>\n<p><span><strong>Verantwoordelijke</strong></span></p>\n<p><span>De verantwoordelijke voor de verwerking is Cody Howest; Rijselstraat 5, 8000 Brugge.</span></p>\n<p><span><strong>Kennisname</strong></span></p>\n<p><span>U kan van deze persoonsgegevens kennis nemen door een aanvraag te richten aan Cody Howest</span><span>(brief, fax of e-mail) en ze, indien nodig, doen verbeteren of verwijderen. Indien u niet gecontacteerd wenst te worden in het kader van email marketing, zullen uw gegevens op uw verzoek kosteloos uit de betrokken lijsten worden</span></p>\n<p><span><strong>Cookies</strong></span></p>\n<p><span>Wij gebruiken cookies om uw toekomstig bezoek aan onze site vlotter te laten verlopen. Een cookie is een klein stukje tekst dat op uw harde schijf wordt geplaatst. Cookies worden veel gebruikt om een hoger functionaliteit, en dus betere dienst, aan de bezoekers te kunnen aanbieden. [U kan het gebruik van cookies uitschakelen, al leidt dit er wel toe dat effecten opsommen die ten gevolge van het uitschakelen van cookies worden veroorzaakt.]</span></p>\n<p><span><strong>Veiligheid</strong></span></p>\n<p><span>Cody Howest verbindt zich ertoe om al de gepaste technische en organisatorische maatregelen te treffen om uw persoonsgegevens te beschermen tegen vernietiging, verlies, onbedoelde wijziging, beschadiging of openbaarmaking.</span></p>\n<p><span><strong>Toestemming</strong></span></p>\n<p><span>Door u akkoord te verklaren met deze voorwaarden en condities geeft u ook uw toestemming voor de verwerking van uw persoonsgegevens voor de doeleinden zoals hierboven beschreven.</span></p>'),
(2,98,'nl',10,'N','T',0,'','<p><span>Door gebruik te maken van deze website verklaart u zich akkoord met onderstaande voorwaarden en condities.</span></p>\n<p><span><strong>1. Website</strong></span></p>\n<p>De eigenaar van deze website is&nbsp;<br /> Cody Howest,<br /> Rijselstraat 5<br /> 8000, Brugge,&nbsp;<br /> Belgi&euml;<br /> Tel: 32(0)50 xx,&nbsp;<br /> E-mail: info@howest.be&nbsp;<br />ON: xx</p>\n<p><span>Als u niet akkoord gaat met onderstaande voorwaarden wordt u verzocht de website te verlaten. Cody behoudt zich het recht voor deze voorwaarden periodisch aan te passen waarna de leden op de hoogte zullen worden gebracht van deze wijzigingen. Wanneer u na deze kennisgeving de website blijft gebruiken verklaart u zich akkoord met de doorgevoerde wijzigingen. Cody Howest&nbsp; kan eventueel andere diensten aanbieden aan de gebruikers van deze site. In dat geval zullen de geldende voorwaarden apart worden medegedeeld.</span></p>\n<p><span><strong>2. Toegankelijkheid</strong></span></p>\n<p><span>Cody Howest&nbsp; probeert zo goed als mogelijk de website 24 uur per dag toegankelijk te houden, nochtans kan het gebeuren dat de website ontoegankelijk is voor een korte periode omwille van onderhoudswerken, aanpassingen of technische redenen.</span></p>\n<p><span><strong>3. Verantwoordelijkheid</strong></span></p>\n<p><span>Cody Howest weerlegt elke verantwoordelijkheid met betrekking tot deze website en de aangeboden informatie. Cody Howest&nbsp; verzekert niet dat de informatie op deze website correct, compleet of actueel is. Alle informatie, producten en diensten op deze website kunnen fouten bevatten. De gebruiker wordt verzocht hiermee rekening te houden.</span></p>\n<div><span><br /></span></div>'),
(7,1,'nl',10,'Y','S',0,'phone','0491-797204'),
(9,1,'nl',20,'Y','S',0,'address','Rijselstraat 1'),

(12,1,'nl',30,'N','S',0,'footer.first','<a href=\"mailto:info@mysite.com\">info@mysite.com</a>'),
(13,1,'nl',40,'N','S',0,'footer.second','<a href=\"/nl/voorwaarden\">Algemene voorwaarden</a>'),
(14,1,'nl',50,'N','S',0,'footer.third',''),
(15,1,'nl',60,'N','S',0,'Google Analytics code','UA-xxxxxxx-4'),

(19,105,'nl',10,'N','T',0,'Text','<h3>Lorem Ipsum - 105</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(20,105,'nl',30,'N','T',0,'Text','<h3>Lorem Ipsum - 105</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(23,106,'nl',30,'N','M',32,'Form',''),
(24,106,'nl',20,'N','T',0,'Text','<h3>Lorem Ipsum - 106</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(29,147,'nl',20,'N','I',0,'Image',''),
(30,150,'nl',10,'N','T',0,'Text','<h3>Lorem Ipsum - 150</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(32,151,'nl',10,'N','T',0,'Text','<h3>Lorem Ipsum - 151</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(35,148,'nl',10,'Y','T',0,'Text','<h3>Lorem Ipsum - 148</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(36,148,'nl',30,'N','S',0,'String','<embed type=\"application/x-shockwave-flash\" src=\"https://static.googleusercontent.com/external_content/picasaweb.googleusercontent.com/slideshow.swf\" width=\"550\" height=\"370\" flashvars=\"host=picasaweb.google.com&hl=en_US&feat=flashalbum&RGB=0x000000&feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2F102890025833311035792%2Falbumid%2F5504535003666704193%3Falt%3Drss%26kind%3Dphoto%26hl%3Den_US\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\"></embed>'),
(37,148,'nl',20,'Y','I',41,'Image',''),
(38,105,'nl',20,'N','F',45,'File',''),
(40,149,'nl',20,'Y','I',42,'Image',''),
(41,149,'nl',10,'Y','T',0,'Text','<h3>Lorem Ipsum - 149</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(42,150,'nl',20,'N','F',37,'File',''),
(43,150,'nl',30,'N','I',43,'Image',''),
(45,147,'nl',10,'N','B',0,'Block','www.mysite.com/[page]'),
(46,152,'nl',10,'N','B',0,'Block','www.mysite.com/[page]'),
(48,153,'nl',10,'N','T',0,'Text','<h3>Lorem Ipsum - 153</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(49,106,'nl',10,'Y','T',0,'Text','<h3>Lorem Ipsum - 106</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(51,155,'nl',10,'N','T',0,'Text','<h3>Lorem Ipsum - 155</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(52,149,'nl',30,'N','S',0,'String','<embed type=\"application/x-shockwave-flash\" src=\"https://static.googleusercontent.com/external_content/picasaweb.googleusercontent.com/slideshow.swf\" width=\"550\" height=\"370\" flashvars=\"host=picasaweb.google.com&hl=en_US&feat=flashalbum&RGB=0x000000&feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2F102890025833311035792%2Falbumid%2F5929480423932141185%3Falt%3Drss%26kind%3Dphoto%26hl%3Den_US\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\"></embed>'),
(53,148,'nl',40,'N','B',0,'Block','www.mysite.com/[page]'),
(54,149,'nl',40,'N','B',0,'Block','www.mysite.com/[page]'),
(55,103,'nl',20,'N','B',0,'Block','www.mysite.com/[page]'),
(56,155,'nl',20,'N','B',0,'Block','https://www.facebook.com/mysite'),
(57,103,'nl',10,'N','T',0,'Text','<h3>Lorem Ipsum - 103</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(58,156,'nl',10,'N','T',0,'Text','<h3>Lorem Ipsum - 156</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(59,157,'nl',10,'N','T',0,'Text','<h3>Lorem Ipsum - 157</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(60,97,'en',10,'N','T',0,'','<p><span>Cody draagt zorg voor uw privacy. Lees deze Privacyverklaring om meer te weten te komen over de manier waarop persoonsgegevens worden ingezameld en verwerkt op deze website. In dit geval handelt Cody Howest daarbij steeds in overeenstemming met de bepalingen van de Belgische privacywet (Wet van 8 december 1992 tot bescherming van de persoonlijke levenssfeer ten opzichte van de verwerking van persoonsgegevens). De persoonlijke gegevens beperken zich enkel tot uw e-mailadres.</span></p>\n<p><span><strong>Verantwoordelijke</strong></span></p>\n<p><span>De verantwoordelijke voor de verwerking is Cody Howest; Rijselstraat 5, 8000 Brugge.</span></p>\n<p><span><strong>Kennisname</strong></span></p>\n<p><span>U kan van deze persoonsgegevens kennis nemen door een aanvraag te richten aan Cody Howest</span><span>(brief, fax of e-mail) en ze, indien nodig, doen verbeteren of verwijderen. Indien u niet gecontacteerd wenst te worden in het kader van email marketing, zullen uw gegevens op uw verzoek kosteloos uit de betrokken lijsten worden</span></p>\n<p><span><strong>Cookies</strong></span></p>\n<p><span>Wij gebruiken cookies om uw toekomstig bezoek aan onze site vlotter te laten verlopen. Een cookie is een klein stukje tekst dat op uw harde schijf wordt geplaatst. Cookies worden veel gebruikt om een hoger functionaliteit, en dus betere dienst, aan de bezoekers te kunnen aanbieden. [U kan het gebruik van cookies uitschakelen, al leidt dit er wel toe dat effecten opsommen die ten gevolge van het uitschakelen van cookies worden veroorzaakt.]</span></p>\n<p><span><strong>Veiligheid</strong></span></p>\n<p><span>Cody Howest verbindt zich ertoe om al de gepaste technische en organisatorische maatregelen te treffen om uw persoonsgegevens te beschermen tegen vernietiging, verlies, onbedoelde wijziging, beschadiging of openbaarmaking.</span></p>\n<p><span><strong>Toestemming</strong></span></p>\n<p><span>Door u akkoord te verklaren met deze voorwaarden en condities geeft u ook uw toestemming voor de verwerking van uw persoonsgegevens voor de doeleinden zoals hierboven beschreven.</span></p>'),
(61,98,'en',10,'N','T',0,'','<p><span>Door gebruik te maken van deze website verklaart u zich akkoord met onderstaande voorwaarden en condities.</span></p>\n<p><span><strong>1. Website</strong></span></p>\n<p>De eigenaar van deze website is&nbsp;<br /> Cody Howest,<br /> Rijselstraat 5<br /> 8000, Brugge,&nbsp;<br /> Belgi&euml;<br /> Tel: 32(0)50 xx,&nbsp;<br /> E-mail: info@howest.be&nbsp;<br />ON: xx</p>\n<p><span>Als u niet akkoord gaat met onderstaande voorwaarden wordt u verzocht de website te verlaten. Cody behoudt zich het recht voor deze voorwaarden periodisch aan te passen waarna de leden op de hoogte zullen worden gebracht van deze wijzigingen. Wanneer u na deze kennisgeving de website blijft gebruiken verklaart u zich akkoord met de doorgevoerde wijzigingen. Cody Howest&nbsp; kan eventueel andere diensten aanbieden aan de gebruikers van deze site. In dat geval zullen de geldende voorwaarden apart worden medegedeeld.</span></p>\n<p><span><strong>2. Toegankelijkheid</strong></span></p>\n<p><span>Cody Howest&nbsp; probeert zo goed als mogelijk de website 24 uur per dag toegankelijk te houden, nochtans kan het gebeuren dat de website ontoegankelijk is voor een korte periode omwille van onderhoudswerken, aanpassingen of technische redenen.</span></p>\n<p><span><strong>3. Verantwoordelijkheid</strong></span></p>\n<p><span>Cody Howest weerlegt elke verantwoordelijkheid met betrekking tot deze website en de aangeboden informatie. Cody Howest&nbsp; verzekert niet dat de informatie op deze website correct, compleet of actueel is. Alle informatie, producten en diensten op deze website kunnen fouten bevatten. De gebruiker wordt verzocht hiermee rekening te houden.</span></p>\n<div><span><br /></span></div>'),
(83,106,'en',20,'N','T',0,'Text','<h3>Lorem Ipsum - 106</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(88,147,'en',20,'N','I',0,'Image',''),
(89,150,'en',10,'N','T',0,'Text','<h3>Lorem Ipsum - 150</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(108,106,'en',10,'Y','T',0,'Text','<h3>Lorem Ipsum - 106</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(74,1,'en',60,'N','S',0,'Google Analytics code','UA-xxxxxxx-4'),
(79,105,'en',30,'N','T',0,'Text','<h3>Lorem Ipsum - 105</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(66,1,'en',10,'Y','S',0,'phone','0491-797204'),
(68,1,'en',20,'Y','S',0,'address','Rijselstraat 1'),
(71,1,'en',30,'N','S',0,'footer.first','<a href=\"mailto:info@mysite.com\">info@mysite.com</a>'),
(72,1,'en',40,'N','S',0,'footer.second','<a href=\"/nl/voorwaarden\">Algemene voorwaarden</a>'),
(73,1,'en',50,'N','S',0,'footer.third',''),
(78,105,'en',10,'N','T',0,'Text','<h3>Lorem Ipsum - 105</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(82,106,'en',30,'N','M',32,'Form',''),
(91,151,'en',10,'N','T',0,'Text','<h3>Lorem Ipsum - 151</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(94,148,'en',10,'Y','T',0,'Text','<h3>Lorem Ipsum - 148</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(95,148,'en',30,'N','S',0,'String','<embed type=\"application/x-shockwave-flash\" src=\"https://static.googleusercontent.com/external_content/picasaweb.googleusercontent.com/slideshow.swf\" width=\"550\" height=\"370\" flashvars=\"host=picasaweb.google.com&hl=en_US&feat=flashalbum&RGB=0x000000&feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2F102890025833311035792%2Falbumid%2F5504535003666704193%3Falt%3Drss%26kind%3Dphoto%26hl%3Den_US\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\"></embed>'),
(96,148,'en',20,'Y','I',41,'Image',''),
(97,105,'en',20,'N','F',45,'File',''),
(99,149,'en',20,'Y','I',42,'Image',''),
(100,149,'en',10,'Y','T',0,'Text','<h3>Lorem Ipsum - 149</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(101,150,'en',20,'N','F',37,'File',''),
(102,150,'en',30,'N','I',43,'Image',''),
(104,147,'en',10,'N','B',0,'Block','www.mysite.com/[page]'),
(105,152,'en',10,'N','B',0,'Block','www.mysite.com/[page]'),
(107,153,'en',10,'N','T',0,'Text','<h3>Lorem Ipsum - 153</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(110,155,'en',10,'N','T',0,'Text','<h3>Lorem Ipsum - 155</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.'),
(111,149,'en',30,'N','S',0,'String','<embed type=\"application/x-shockwave-flash\" src=\"https://static.googleusercontent.com/external_content/picasaweb.googleusercontent.com/slideshow.swf\" width=\"550\" height=\"370\" flashvars=\"host=picasaweb.google.com&hl=en_US&feat=flashalbum&RGB=0x000000&feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2F102890025833311035792%2Falbumid%2F5929480423932141185%3Falt%3Drss%26kind%3Dphoto%26hl%3Den_US\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\"></embed>'),
(112,148,'en',40,'N','B',0,'Block','www.mysite.com/[page]'),
(113,149,'en',40,'N','B',0,'Block','www.mysite.com/[page]'),
(114,103,'en',20,'N','B',0,'Block','www.mysite.com/[page]'),
(115,155,'en',20,'N','B',0,'Block','https://www.facebook.com/mysite'),
(116,103,'en',10,'N','T',0,'Text','<h3>Lorem Ipsum - 103</h3>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima
Download .txt
gitextract_3aeu67e9/

├── .gitignore
├── .npmignore
├── Contributing.md
├── History.md
├── LICENSE.md
├── README.md
├── apps/
│   ├── Application.js
│   ├── Dynamic.js
│   └── Static.js
├── bin/
│   ├── create_site.js
│   └── remove_site
├── controllers/
│   ├── ContactController.js
│   ├── Controller.js
│   ├── DashboardController.js
│   ├── EmailController.js
│   ├── FileController.js
│   ├── FormController.js
│   ├── FormDataController.js
│   ├── ImageController.js
│   ├── LoginController.js
│   ├── PageController.js
│   ├── StylesController.js
│   ├── SystemController.js
│   ├── TemplateController.js
│   ├── TreeController.js
│   └── UserController.js
├── doc/
│   ├── Context.txt
│   ├── empty/
│   │   ├── controllers/
│   │   │   └── YourController.js
│   │   ├── empty.sql
│   │   ├── index.js
│   │   ├── locales/
│   │   │   ├── en.json
│   │   │   └── zh-CN.json
│   │   ├── static/
│   │   │   ├── css/
│   │   │   │   └── front.css
│   │   │   └── js/
│   │   │       └── script.js
│   │   └── views/
│   │       ├── content.ejs
│   │       ├── footer.ejs
│   │       ├── header.ejs
│   │       ├── index.ejs
│   │       ├── intros.ejs
│   │       ├── menu-left.ejs
│   │       ├── menu-top.ejs
│   │       └── page.ejs
│   ├── hosting_sqlbased/
│   │   ├── codymaster.sql
│   │   └── index.js
│   └── todo.txt
├── index.js
├── makeWebApp.js
├── models/
│   ├── Atom.js
│   ├── Content.js
│   ├── Context.js
│   ├── Item.js
│   ├── Meta.js
│   ├── Model.js
│   ├── Page.js
│   ├── Path.js
│   ├── Template.js
│   ├── User.js
│   └── Website.js
├── package.json
├── startWebApp.js
├── startserver.js
├── static/
│   ├── css/
│   │   ├── cody.css
│   │   └── ui-lightness/
│   │       └── jquery-ui-1.10.1.css
│   └── js/
│       ├── atom-tree.js
│       ├── lib/
│       │   ├── html5shiv.js
│       │   ├── jquery-1.9.1.js
│       │   ├── jquery-ui-1.10.1.js
│       │   ├── jquery.jstree.js
│       │   ├── jquery.validate.js
│       │   ├── localization/
│       │   │   ├── jquery.ui.datepicker-de.js
│       │   │   ├── jquery.ui.datepicker-en.js
│       │   │   ├── jquery.ui.datepicker-es.js
│       │   │   ├── jquery.ui.datepicker-fr.js
│       │   │   ├── jquery.ui.datepicker-nl.js
│       │   │   ├── messages_de.js
│       │   │   ├── messages_en.js
│       │   │   ├── messages_es.js
│       │   │   ├── messages_fr.js
│       │   │   └── messages_nl.js
│       │   └── themes/
│       │       ├── apple/
│       │       │   └── style.css
│       │       ├── classic/
│       │       │   └── style.css
│       │       └── default/
│       │           └── style.css
│       ├── pages-editor.js
│       ├── script.js
│       └── tinymce/
│           ├── jquery.tinymce.js
│           ├── langs/
│           │   └── en.js
│           ├── license.txt
│           ├── plugins/
│           │   ├── advhr/
│           │   │   ├── css/
│           │   │   │   └── advhr.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── rule.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   └── rule.htm
│           │   ├── advimage/
│           │   │   ├── css/
│           │   │   │   └── advimage.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── image.htm
│           │   │   ├── js/
│           │   │   │   └── image.js
│           │   │   └── langs/
│           │   │       └── en_dlg.js
│           │   ├── advlink/
│           │   │   ├── css/
│           │   │   │   └── advlink.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── advlink.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   └── link.htm
│           │   ├── advlist/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── autolink/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── autoresize/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── autosave/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── bbcode/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── contextmenu/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── directionality/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── emotions/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── emotions.htm
│           │   │   ├── js/
│           │   │   │   └── emotions.js
│           │   │   └── langs/
│           │   │       └── en_dlg.js
│           │   ├── example/
│           │   │   ├── dialog.htm
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── dialog.js
│           │   │   └── langs/
│           │   │       ├── en.js
│           │   │       └── en_dlg.js
│           │   ├── example_dependency/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── fullpage/
│           │   │   ├── css/
│           │   │   │   └── fullpage.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── fullpage.htm
│           │   │   ├── js/
│           │   │   │   └── fullpage.js
│           │   │   └── langs/
│           │   │       └── en_dlg.js
│           │   ├── fullscreen/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   └── fullscreen.htm
│           │   ├── iespell/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── inlinepopups/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── skins/
│           │   │   │   └── clearlooks2/
│           │   │   │       └── window.css
│           │   │   └── template.htm
│           │   ├── insertdatetime/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── layer/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── legacyoutput/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── lists/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── media/
│           │   │   ├── css/
│           │   │   │   └── media.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   ├── embed.js
│           │   │   │   └── media.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   ├── media.htm
│           │   │   └── moxieplayer.swf
│           │   ├── nonbreaking/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── noneditable/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── pagebreak/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── paste/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   ├── pastetext.js
│           │   │   │   └── pasteword.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   ├── pastetext.htm
│           │   │   └── pasteword.htm
│           │   ├── preview/
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── example.html
│           │   │   ├── jscripts/
│           │   │   │   └── embed.js
│           │   │   └── preview.html
│           │   ├── print/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── save/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── searchreplace/
│           │   │   ├── css/
│           │   │   │   └── searchreplace.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── searchreplace.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   └── searchreplace.htm
│           │   ├── spellchecker/
│           │   │   ├── css/
│           │   │   │   └── content.css
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── style/
│           │   │   ├── css/
│           │   │   │   └── props.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── props.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   ├── props.htm
│           │   │   └── readme.txt
│           │   ├── tabfocus/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── table/
│           │   │   ├── cell.htm
│           │   │   ├── css/
│           │   │   │   ├── cell.css
│           │   │   │   ├── row.css
│           │   │   │   └── table.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   ├── cell.js
│           │   │   │   ├── merge_cells.js
│           │   │   │   ├── row.js
│           │   │   │   └── table.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   ├── merge_cells.htm
│           │   │   ├── row.htm
│           │   │   └── table.htm
│           │   ├── template/
│           │   │   ├── blank.htm
│           │   │   ├── css/
│           │   │   │   └── template.css
│           │   │   ├── editor_plugin.js
│           │   │   ├── editor_plugin_src.js
│           │   │   ├── js/
│           │   │   │   └── template.js
│           │   │   ├── langs/
│           │   │   │   └── en_dlg.js
│           │   │   └── template.htm
│           │   ├── visualblocks/
│           │   │   ├── css/
│           │   │   │   └── visualblocks.css
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── visualchars/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   ├── wordcount/
│           │   │   ├── editor_plugin.js
│           │   │   └── editor_plugin_src.js
│           │   └── xhtmlxtras/
│           │       ├── abbr.htm
│           │       ├── acronym.htm
│           │       ├── attributes.htm
│           │       ├── cite.htm
│           │       ├── css/
│           │       │   ├── attributes.css
│           │       │   └── popup.css
│           │       ├── del.htm
│           │       ├── editor_plugin.js
│           │       ├── editor_plugin_src.js
│           │       ├── ins.htm
│           │       ├── js/
│           │       │   ├── abbr.js
│           │       │   ├── acronym.js
│           │       │   ├── attributes.js
│           │       │   ├── cite.js
│           │       │   ├── del.js
│           │       │   ├── element_common.js
│           │       │   └── ins.js
│           │       └── langs/
│           │           └── en_dlg.js
│           ├── themes/
│           │   ├── advanced/
│           │   │   ├── about.htm
│           │   │   ├── anchor.htm
│           │   │   ├── charmap.htm
│           │   │   ├── color_picker.htm
│           │   │   ├── editor_template.js
│           │   │   ├── editor_template_src.js
│           │   │   ├── image.htm
│           │   │   ├── js/
│           │   │   │   ├── about.js
│           │   │   │   ├── anchor.js
│           │   │   │   ├── charmap.js
│           │   │   │   ├── color_picker.js
│           │   │   │   ├── image.js
│           │   │   │   ├── link.js
│           │   │   │   └── source_editor.js
│           │   │   ├── langs/
│           │   │   │   ├── en.js
│           │   │   │   └── en_dlg.js
│           │   │   ├── link.htm
│           │   │   ├── shortcuts.htm
│           │   │   ├── skins/
│           │   │   │   ├── default/
│           │   │   │   │   ├── content.css
│           │   │   │   │   ├── dialog.css
│           │   │   │   │   └── ui.css
│           │   │   │   ├── highcontrast/
│           │   │   │   │   ├── content.css
│           │   │   │   │   ├── dialog.css
│           │   │   │   │   └── ui.css
│           │   │   │   └── o2k7/
│           │   │   │       ├── content.css
│           │   │   │       ├── dialog.css
│           │   │   │       ├── ui.css
│           │   │   │       ├── ui_black.css
│           │   │   │       └── ui_silver.css
│           │   │   └── source_editor.htm
│           │   └── simple/
│           │       ├── editor_template.js
│           │       ├── editor_template_src.js
│           │       ├── langs/
│           │       │   └── en.js
│           │       └── skins/
│           │           ├── default/
│           │           │   ├── content.css
│           │           │   └── ui.css
│           │           └── o2k7/
│           │               ├── content.css
│           │               └── ui.css
│           ├── tiny_mce.js
│           ├── tiny_mce_popup.js
│           ├── tiny_mce_src.js
│           └── utils/
│               ├── editable_selects.js
│               ├── form_utils.js
│               ├── mctabs.js
│               └── validate.js
├── testing/
│   └── testdynamic.js
└── views/
    ├── cms/
    │   ├── comments-ajax.ejs
    │   ├── comments.ejs
    │   ├── contacts.ejs
    │   ├── content-type.ejs
    │   ├── dashboard.ejs
    │   ├── files-ajax.ejs
    │   ├── files.ejs
    │   ├── footer.ejs
    │   ├── forms-ajax.ejs
    │   ├── forms-data.ejs
    │   ├── forms-list.ejs
    │   ├── forms.ejs
    │   ├── header.ejs
    │   ├── images-ajax.ejs
    │   ├── images.ejs
    │   ├── navigation.ejs
    │   ├── pages-ajax.ejs
    │   ├── pages.ejs
    │   ├── styles.ejs
    │   ├── system.ejs
    │   ├── templates.ejs
    │   ├── top.ejs
    │   └── users.ejs
    ├── front/
    │   └── index.ejs
    └── login.ejs
Download .txt
SYMBOL INDEX (915 symbols across 109 files)

FILE: apps/Application.js
  function Application (line 15) | function Application(config) {
  function one (line 185) | function one(current) {
  function one (line 220) | function one(current) {
  function connectToDatabase (line 417) | function connectToDatabase() {
  function printPage (line 810) | function printPage(lan, id) {
  function printLevel (line 819) | function printLevel(r, nr) {
  function printChildren (line 829) | function printChildren(lan, id) {

FILE: apps/Dynamic.js
  function generate404 (line 17) | function generate404(resp) {
  function Dynamic (line 23) | function Dynamic(req, res, path, prefix) {

FILE: apps/Static.js
  function Static (line 21) | function Static(req, res, appFolder, prefix) {

FILE: controllers/ContactController.js
  function ContactController (line 49) | function ContactController(context) {
  function ffield (line 160) | function ffield(obj, nameArr) {

FILE: controllers/Controller.js
  function Controller (line 12) | function Controller(context) {

FILE: controllers/DashboardController.js
  function DashboardController (line 10) | function DashboardController(context) {

FILE: controllers/EmailController.js
  function EmailController (line 11) | function EmailController (context) {

FILE: controllers/FileController.js
  function FileController (line 11) | function FileController(context) {

FILE: controllers/FormController.js
  function FormController (line 44) | function FormController(context) {

FILE: controllers/FormDataController.js
  function FormDataController (line 10) | function FormDataController(context) {

FILE: controllers/ImageController.js
  function ImageController (line 11) | function ImageController(context) {

FILE: controllers/LoginController.js
  function LoginController (line 11) | function LoginController(context) {

FILE: controllers/PageController.js
  function Root (line 13) | function Root(controller, id, name) {
  function PageController (line 26) | function PageController(context) {

FILE: controllers/StylesController.js
  function StylesController (line 13) | function StylesController(context) {

FILE: controllers/SystemController.js
  function SystemController (line 14) | function SystemController(context) {

FILE: controllers/TemplateController.js
  function TemplateController (line 11) | function TemplateController(context) {

FILE: controllers/TreeController.js
  function TreeController (line 13) | function TreeController(context) {
  function dashes (line 144) | function dashes(cnt) {
  function renderArray (line 150) | function renderArray( theNode, level ) {
  function renderTree (line 173) | function renderTree( theNode ) {
  function renderTree (line 193) | function renderTree( theNode ) {
  function renderTree (line 219) | function renderTree( theNode, open, descend ) {

FILE: controllers/UserController.js
  function UserController (line 11) | function UserController(context) {

FILE: doc/empty/controllers/YourController.js
  function YourController (line 5) | function YourController(context) {

FILE: doc/empty/empty.sql
  function PASSWORD2 (line 3) | CREATE FUNCTION PASSWORD2(s VARCHAR(50))
  type `atoms` (line 9) | CREATE TABLE `atoms` (
  type `content` (line 51) | CREATE TABLE `content` (
  type `data` (line 146) | CREATE TABLE `data` (
  type `domains` (line 166) | CREATE TABLE `domains` (
  type `items` (line 182) | CREATE TABLE `items` (
  type `languages` (line 243) | CREATE TABLE `languages` (
  type `levels` (line 257) | CREATE TABLE `levels` (
  type `pages` (line 272) | CREATE TABLE `pages` (
  type `templates` (line 363) | CREATE TABLE `templates` (
  type `users` (line 398) | CREATE TABLE `users` (

FILE: doc/hosting_sqlbased/codymaster.sql
  type `websites` (line 23) | CREATE TABLE IF NOT EXISTS `websites` (
  type nameIndex (line 39) | create unique index nameIndex on cody.websites(name)

FILE: makeWebApp.js
  function doLanguage (line 131) | function doLanguage(lan) {

FILE: models/Atom.js
  function Atom (line 13) | function Atom(basis) {

FILE: models/Content.js
  function Content (line 10) | function Content(basis, app) {

FILE: models/Context.js
  function Context (line 19) | function Context(path, page, app, req, res) {
  function two (line 326) | function two(n) {

FILE: models/Item.js
  function Item (line 13) | function Item(basis, app) {

FILE: models/Meta.js
  function Meta (line 10) | function Meta(plainObject) {
  function getClasses (line 508) | function getClasses(object, extraClass) {
  function getAttributes (line 534) | function getAttributes(object) {
  function getErrors (line 551) | function getErrors(lang, object) {
  function validLang (line 558) | function validLang(lang) {
  function getVal (line 561) | function getVal(object) {
  function getTVal (line 564) | function getTVal(object) {
  function isIn (line 567) | function isIn(val, values) {
  function two (line 571) | function two(n) {
  function getRadios (line 577) | function getRadios(lang, object, cls) {
  function getOptions (line 585) | function getOptions(lang, object) {
  function getChecks (line 593) | function getChecks(lang, object) {
  function demo (line 734) | function demo() {

FILE: models/Model.js
  function Model (line 13) | function Model(theController, options) {

FILE: models/Page.js
  function Page (line 10) | function Page(basis, app) {
  function goUp (line 109) | function goUp(aPage) {

FILE: models/Path.js
  function Path (line 1) | function Path( path, deflanguage ) {

FILE: models/Template.js
  function Template (line 10) | function Template(basis, controllers) {

FILE: models/User.js
  function User (line 10) | function User(basis) {

FILE: startWebApp.js
  function startWebApp (line 7) | function startWebApp(mainServer, config, done) {

FILE: startserver.js
  function startApp (line 158) | function startApp( application ) {
  function startHost (line 184) | function startHost( host, app, certContext ) {

FILE: static/js/atom-tree.js
  function jAtomTree (line 11) | function jAtomTree(theRoot, theInitialNode, theLanguage, theService, the...

FILE: static/js/lib/html5shiv.js
  function addStyleSheet (line 67) | function addStyleSheet(ownerDocument, cssText) {
  function getElements (line 80) | function getElements() {
  function getExpandoData (line 91) | function getExpandoData(ownerDocument) {
  function createElement (line 109) | function createElement(nodeName, ownerDocument, data){
  function createDocumentFragment (line 145) | function createDocumentFragment(ownerDocument, data){
  function shivMethods (line 169) | function shivMethods(ownerDocument, data) {
  function shivDocument (line 207) | function shivDocument(ownerDocument) {

FILE: static/js/lib/jquery-1.9.1.js
  function isArraylike (line 951) | function isArraylike( obj ) {
  function createOptions (line 974) | function createOptions( options ) {
  function internalData (line 1551) | function internalData( elem, name, data, pvt /* Internal Use Only */ ){
  function internalRemoveData (line 1645) | function internalRemoveData( elem, name, pvt ) {
  function dataAttr (line 1841) | function dataAttr( elem, key, data ) {
  function isEmptyDataObject (line 1873) | function isEmptyDataObject( obj ) {
  function returnTrue (line 2702) | function returnTrue() {
  function returnFalse (line 2706) | function returnFalse() {
  function isNative (line 3841) | function isNative( fn ) {
  function createCache (line 3851) | function createCache() {
  function markFunction (line 3869) | function markFunction( fn ) {
  function assert (line 3878) | function assert( fn ) {
  function Sizzle (line 3891) | function Sizzle( selector, context, results, seed ) {
  function siblingCheck (line 4449) | function siblingCheck( a, b ) {
  function createInputPseudo (line 4471) | function createInputPseudo( type ) {
  function createButtonPseudo (line 4479) | function createButtonPseudo( type ) {
  function createPositionalPseudo (line 4487) | function createPositionalPseudo( fn ) {
  function tokenize (line 5014) | function tokenize( selector, parseOnly ) {
  function toSelector (line 5081) | function toSelector( tokens ) {
  function addCombinator (line 5091) | function addCombinator( matcher, combinator, base ) {
  function elementMatcher (line 5141) | function elementMatcher( matchers ) {
  function condense (line 5155) | function condense( unmatched, map, filter, context, xml ) {
  function setMatcher (line 5176) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
  function matcherFromTokens (line 5269) | function matcherFromTokens( tokens ) {
  function matcherFromGroupMatchers (line 5321) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  function multipleContexts (line 5449) | function multipleContexts( selector, contexts, results ) {
  function select (line 5458) | function select( selector, context, results, seed ) {
  function setFilters (line 5527) | function setFilters() {}
  function sibling (line 5680) | function sibling( cur, dir ) {
  function winnow (line 5788) | function winnow( elements, qualifier, keep ) {
  function createSafeFragment (line 5821) | function createSafeFragment( document ) {
  function findOrAppend (line 6202) | function findOrAppend( elem, tag ) {
  function disableScript (line 6207) | function disableScript( elem ) {
  function restoreScript (line 6212) | function restoreScript( elem ) {
  function setGlobalEval (line 6223) | function setGlobalEval( elems, refElements ) {
  function cloneCopyEvent (line 6231) | function cloneCopyEvent( src, dest ) {
  function fixCloneNodeIssues (line 6259) | function fixCloneNodeIssues( src, dest ) {
  function getAll (line 6352) | function getAll( context, tag ) {
  function fixDefaultChecked (line 6375) | function fixDefaultChecked( elem ) {
  function vendorPropName (line 6640) | function vendorPropName( style, name ) {
  function isHidden (line 6662) | function isHidden( elem, el ) {
  function showHide (line 6669) | function showHide( elements, show ) {
  function setPositiveNumber (line 7016) | function setPositiveNumber( elem, value, subtract ) {
  function augmentWidthOrHeight (line 7024) | function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
  function getWidthOrHeight (line 7063) | function getWidthOrHeight( elem, name, extra ) {
  function css_defaultDisplay (line 7107) | function css_defaultDisplay( nodeName ) {
  function actualDisplay (line 7139) | function actualDisplay( name, doc ) {
  function buildParams (line 7368) | function buildParams( prefix, obj, traditional, add ) {
  function addToPrefiltersOrTransports (line 7466) | function addToPrefiltersOrTransports( structure ) {
  function inspectPrefiltersOrTransports (line 7498) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
  function ajaxExtend (line 7525) | function ajaxExtend( target, src ) {
  function done (line 7991) | function done( status, nativeStatusText, responses, headers ) {
  function ajaxHandleResponses (line 8117) | function ajaxHandleResponses( s, jqXHR, responses ) {
  function ajaxConvert (line 8178) | function ajaxConvert( s, response ) {
  function createStandardXHR (line 8439) | function createStandardXHR() {
  function createActiveXHR (line 8445) | function createActiveXHR() {
  function createFxNow (line 8684) | function createFxNow() {
  function createTweens (line 8691) | function createTweens( animation, props ) {
  function Animation (line 8706) | function Animation( elem, properties, options ) {
  function propFilter (line 8810) | function propFilter( props, specialEasing ) {
  function defaultPrefilter (line 8877) | function defaultPrefilter( elem, props, opts ) {
  function Tween (line 9004) | function Tween( elem, options, prop, end, easing ) {
  function genFx (line 9230) | function genFx( type, includeWidth ) {
  function getWindow (line 9526) | function getWindow( elem ) {

FILE: static/js/lib/jquery-ui-1.10.1.js
  function focusable (line 127) | function focusable( element, isTabIndexNotNaN ) {
  function visible (line 148) | function visible( element ) {
  function reduce (line 190) | function reduce( elem, size, border, margin ) {
  function handlerProxy (line 696) | function handlerProxy() {
  function handlerProxy (line 732) | function handlerProxy() {
  function getOffsets (line 1002) | function getOffsets( offsets, width, height ) {
  function parseCss (line 1009) | function parseCss( element, property ) {
  function getDimensions (line 1013) | function getDimensions( elem ) {
  function isOverAxis (line 2404) | function isOverAxis( x, reference, size ) {
  function num (line 2759) | function num(v) {
  function isNumber (line 2763) | function isNumber(value) {
  function isOverAxis (line 3976) | function isOverAxis( x, reference, size ) {
  function Datepicker (line 6775) | function Datepicker() {
  function bindHover (line 8714) | function bindHover(dpDiv) {
  function extendRemove (line 8740) | function extendRemove(target, props) {
  function checkFocus (line 9036) | function checkFocus() {
  function filteredUi (line 9213) | function filteredUi( ui ) {
  function filteredUi (line 9255) | function filteredUi( ui ) {
  function escape (line 9744) | function escape( value ) {
  function modifier (line 10975) | function modifier( fn ) {
  function checkFocus (line 11094) | function checkFocus() {
  function getNextTabId (line 11455) | function getNextTabId() {
  function isLocal (line 11459) | function isLocal( anchor ) {
  function constrain (line 11676) | function constrain() {
  function complete (line 12022) | function complete() {
  function show (line 12027) | function show() {
  function addDescribedBy (line 12286) | function addDescribedBy( elem, id ) {
  function removeDescribedBy (line 12294) | function removeDescribedBy( elem ) {
  function position (line 12515) | function position( event ) {
  function clamp (line 12825) | function clamp( value, prop, allowEmpty ) {
  function stringParse (line 12851) | function stringParse( string ) {
  function hue2rgb (line 13101) | function hue2rgb( p, q, h ) {
  function getElementStyles (line 13369) | function getElementStyles( elem ) {
  function styleDifference (line 13397) | function styleDifference( oldStyle, newStyle ) {
  function _normalizeArguments (line 13715) | function _normalizeArguments( effect, options, speed, callback ) {
  function standardSpeed (line 13767) | function standardSpeed( speed ) {
  function run (line 13797) | function run( next ) {
  function childComplete (line 14224) | function childComplete() {
  function animComplete (line 14273) | function animComplete() {

FILE: static/js/lib/jquery.jstree.js
  function exec (line 1496) | function exec(i, event) {

FILE: static/js/lib/jquery.validate.js
  function handle (line 49) | function handle() {
  function delegate (line 315) | function delegate(event) {

FILE: static/js/pages-editor.js
  function addPage (line 49) | function addPage() {
  function selectedTemplate (line 60) | function selectedTemplate() {
  function getPage (line 74) | function getPage(id) {
  function initPage (line 101) | function initPage(id) {
  function doView (line 157) | function doView() {
  function doDeletor (line 162) | function doDeletor() {
  function doAdjust (line 182) | function doAdjust() {
  function doAddContent (line 202) | function doAddContent() {
  function selectedContent (line 207) | function selectedContent() {
  function doAtomEditor (line 243) | function doAtomEditor(button, type, feedback) {
  function doEditorI (line 288) | function doEditorI() { console.log("doEditorI");
  function doEditorF (line 298) | function doEditorF() {
  function doEditorT (line 310) | function doEditorT() {
  function doSaveEditor (line 319) | function doSaveEditor() {
  function doCancelEditor (line 322) | function doCancelEditor() {
  function hideEditor (line 326) | function hideEditor() {
  function showEditor (line 333) | function showEditor( content ) {
  function saveEditor (line 341) | function saveEditor(theId) {
  function saveOrder (line 390) | function saveOrder() {

FILE: static/js/tinymce/jquery.tinymce.js
  function o (line 1) | function o(){var r=[],q=0;if(f){f();f=null}p.each(function(t,u){var s,w=...
  function q (line 1) | function q(r){tinymce.ScriptLoader.markDone(tinyMCE.baseURI.toAbsolute(r))}
  function f (line 1) | function f(){function i(l){if(l==="remove"){this.each(function(n,o){var ...

FILE: static/js/tinymce/plugins/advlink/js/advlink.js
  function preinit (line 9) | function preinit() {
  function changeClass (line 16) | function changeClass() {
  function init (line 22) | function init() {
  function checkPrefix (line 128) | function checkPrefix(n) {
  function setFormValue (line 136) | function setFormValue(name, value) {
  function parseWindowOpen (line 140) | function parseWindowOpen(onclick) {
  function parseFunction (line 185) | function parseFunction(onclick) {
  function getOption (line 192) | function getOption(opts, name) {
  function setPopupControlsDisabled (line 196) | function setPopupControlsDisabled(state) {
  function parseLink (line 217) | function parseLink(link) {
  function parseOptions (line 263) | function parseOptions(opts) {
  function buildOnClick (line 285) | function buildOnClick() {
  function setAttrib (line 356) | function setAttrib(elm, attrib, value) {
  function getAnchorListHTML (line 375) | function getAnchorListHTML(id, target) {
  function insertAction (line 399) | function insertAction() {
  function setAllAttribs (line 441) | function setAllAttribs(elm) {
  function getSelectValue (line 479) | function getSelectValue(form_obj, field_name) {
  function getLinkListHTML (line 488) | function getLinkListHTML(elm_id, target_form_element, onchange_func) {
  function getTargetListHTML (line 513) | function getTargetListHTML(elm_id, target_form_element) {

FILE: static/js/tinymce/plugins/advlist/editor_plugin.js
  function e (line 1) | function e(g){var f=[];a(g.split(/,/),function(h){f.push({title:"advlist...
  function c (line 1) | function c(j,l){var k=true;a(l.styles,function(n,m){if(g.dom.getStyle(j,...
  function h (line 1) | function h(){var k,l=g.dom,j=g.selection;k=l.getParent(j.getNode(),"ol,u...

FILE: static/js/tinymce/plugins/advlist/editor_plugin_src.js
  function buildFormats (line 20) | function buildFormats(str) {
  function hasFormat (line 51) | function hasFormat(node, format) {
  function applyListFormat (line 65) | function applyListFormat() {

FILE: static/js/tinymce/plugins/autoresize/editor_plugin.js
  function b (line 1) | function b(){var j,i=a.getDoc(),f=i.body,l=i.documentElement,h=tinymce.D...

FILE: static/js/tinymce/plugins/autoresize/editor_plugin_src.js
  function resize (line 37) | function resize() {

FILE: static/js/tinymce/plugins/autosave/editor_plugin.js
  function k (line 1) | function k(n){var m={s:1000,m:60000};n=/^(\d+)([ms]?)$/.exec(""+n);retur...

FILE: static/js/tinymce/plugins/autosave/editor_plugin_src.js
  function parseTime (line 77) | function parseTime(time) {

FILE: static/js/tinymce/plugins/bbcode/editor_plugin.js
  function b (line 1) | function b(c,d){a=a.replace(c,d)}
  function b (line 1) | function b(c,d){a=a.replace(c,d)}

FILE: static/js/tinymce/plugins/bbcode/editor_plugin_src.js
  function rep (line 45) | function rep(re, str) {
  function rep (line 95) | function rep(re, str) {

FILE: static/js/tinymce/plugins/contextmenu/editor_plugin.js
  function h (line 1) | function h(k,l){j=0;if(l&&l.button==2){j=l.ctrlKey;return}if(i._menu){i....

FILE: static/js/tinymce/plugins/contextmenu/editor_plugin_src.js
  function hide (line 71) | function hide(ed, e) {

FILE: static/js/tinymce/plugins/directionality/editor_plugin.js
  function a (line 1) | function a(e){var h=b.dom,g,f=b.selection.getSelectedBlocks();if(f.lengt...

FILE: static/js/tinymce/plugins/directionality/editor_plugin_src.js
  function setDir (line 18) | function setDir(dir) {

FILE: static/js/tinymce/plugins/fullpage/editor_plugin.js
  function d (line 1) | function d(l,j){var k=l.attr(j);return k||""}
  function c (line 1) | function c(n,l,m){n.attr(l,m?m:undefined)}
  function i (line 1) | function i(l){if(d.firstChild){d.insert(l,d.firstChild)}else{d.append(l)}}
  function k (line 1) | function k(n){return n.replace(/<\/?[A-Z]+/g,function(o){return o.toLowe...

FILE: static/js/tinymce/plugins/fullpage/editor_plugin_src.js
  function getAttr (line 55) | function getAttr(elm, name) {
  function setAttr (line 125) | function setAttr(elm, name, value) {
  function addHeadNode (line 129) | function addHeadNode(node) {
  function low (line 304) | function low(s) {

FILE: static/js/tinymce/plugins/fullpage/js/fullpage.js
  function setVal (line 37) | function setVal(id, value) {
  function getVal (line 52) | function getVal(id) {
  function init (line 162) | function init() {

FILE: static/js/tinymce/plugins/inlinepopups/editor_plugin.js
  function D (line 1) | function D(){if(f){return}o._fixIELayout(v,0);d.add(C.body,"div",{id:"mc...

FILE: static/js/tinymce/plugins/inlinepopups/editor_plugin_src.js
  function startMove (line 404) | function startMove() {

FILE: static/js/tinymce/plugins/insertdatetime/editor_plugin.js
  function b (line 1) | function b(g,d){g=""+g;if(g.length<d){for(var f=0;f<(d-g.length);f++){g=...

FILE: static/js/tinymce/plugins/insertdatetime/editor_plugin_src.js
  function addZeros (line 49) | function addZeros(value, len) {

FILE: static/js/tinymce/plugins/layer/editor_plugin.js
  function a (line 1) | function a(b){do{if(b.className&&b.className.indexOf("mceItemLayer")!=-1...

FILE: static/js/tinymce/plugins/layer/editor_plugin_src.js
  function findParentLayer (line 12) | function findParentLayer(node) {

FILE: static/js/tinymce/plugins/lists/editor_plugin.js
  function p (line 1) | function p(t,s){while(t&&(t.nodeType===8||(t.nodeType===3&&/^[ \t\n\r]*$...
  function b (line 1) | function b(s){return p(s,function(t){return t.previousSibling})}
  function i (line 1) | function i(s){return p(s,function(t){return t.nextSibling})}
  function d (line 1) | function d(s,u,t){return s.dom.getParent(u,function(v){return tinymce.in...
  function n (line 1) | function n(s){return s&&(s.tagName==="OL"||s.tagName==="UL")}
  function c (line 1) | function c(u,v){var t,w,s;t=b(u.lastChild);while(n(t)){w=t;t=b(w.previou...
  function m (line 1) | function m(t,s,u){t=a(t,s,u);return o(t,s,u)}
  function a (line 1) | function a(u,s,v){var t=b(u.previousSibling);if(t){return h(t,u,s?t:fals...
  function o (line 1) | function o(u,t,v){var s=i(u.nextSibling);if(s){return h(u,s,t?s:false,v)...
  function h (line 1) | function h(u,s,t,v){if(l(u,s,!!t,v)){return f(u,s,t)}else{if(u&&u.tagNam...
  function l (line 1) | function l(u,t,s,v){if(!u||!t){return false}else{if(u.tagName==="LI"&&t....
  function q (line 1) | function q(t){var s=i(t.firstChild),u=b(t.lastChild);return s&&u&&n(t)&&...
  function j (line 1) | function j(u){var t=i(u.firstChild),s=b(u.lastChild);return t&&s&&t===s&...
  function f (line 1) | function f(w,v,s){var u=b(w.lastChild),t=i(v.firstChild);if(w.tagName===...
  function k (line 1) | function k(t,u){var s;if(!u.is(t,"li,ol,ul")){s=u.getParent(t,"li");if(s...
  function E (line 1) | function E(U){return U.keyCode===tinymce.VK.TAB&&!(U.altKey||U.ctrlKey)&...
  function w (line 1) | function w(){var U=B();var W=U.parentNode.parentNode;var V=U.parentNode....
  function t (line 1) | function t(U){if(n(U)){return U.parentNode&&U.parentNode.tagName==="LI"}...
  function F (line 1) | function F(){return y.selection.isCollapsed()&&P(B())}
  function B (line 1) | function B(){var U=y.selection.getStart();return((U.tagName=="BR"||U.tag...
  function P (line 1) | function P(U){var V=U.childNodes.length;if(U.tagName==="LI"){return V==0...
  function H (line 1) | function H(U){var V=tinymce.grep(U.parentNode.childNodes,function(Y){ret...
  function T (line 1) | function T(U){return U.keyCode===tinymce.VK.ENTER}
  function A (line 1) | function A(U){return T(U)&&!U.shiftKey}
  function M (line 1) | function M(U){if(E(U)){return v}else{if(A(U)&&w()){return N}else{if(A(U)...
  function D (line 1) | function D(U,V){if(x==v||x==s||tinymce.isGecko&&x==J){r.cancel(V)}}
  function C (line 1) | function C(){var U=y.selection.getRng(true);var V=U.startContainer;if(V....
  function I (line 1) | function I(){var W=y.selection.getNode();var V="h1,h2,h3,h4,h5,h6,p,div"...
  function K (line 1) | function K(W,Y){if(A(Y)&&I()){var X=W.selection.getNode();var V=W.dom.cr...
  function u (line 1) | function u(X,Z){var ac;if(!tinymce.isGecko){return}var V=X.selection.get...
  function G (line 1) | function G(U){var V=y.dom.getParent(U,"ol,ul");if(V!=null){var W=V.lastC...
  function U (line 1) | function U(X){X=W.getParent(X,W.isBlock);return X&&(parseInt(y.dom.getSt...
  function L (line 1) | function L(V,U){var W=y.getDoc().createTextNode("\uFEFF");V.insertBefore...
  function R (line 1) | function R(V,X){if(T(X)){var U=B();if(U){var W=U.parentNode;var Y=W&&W.p...
  function S (line 1) | function S(V,X){if(T(X)){var U=B();if(V.dom.select("ul li",U).length===1...
  function Q (line 1) | function Q(W,aa){function X(ab){var ad=[];var ae=new tinymce.dom.TreeWal...
  function O (line 1) | function O(V,X){var U=B();if(X.keyCode===tinymce.VK.BACKSPACE&&V.dom.is(...
  function E (line 1) | function E(t){if(t&&t.tagName==="BR"){I.remove(t)}}
  function F (line 1) | function F(M){var N=I.create(y),t;function L(O){if(O.style.marginLeft||O...
  function J (line 1) | function J(P,L,N){var t,O=P,M;while(!I.isBlock(P.parentNode)&&P.parentNo...
  function K (line 1) | function K(Q,T){var N,R,O=3,L=1,t="br,ul,ol,p,div,h1,h2,h3,h4,h5,h6,tabl...
  function D (line 1) | function D(t){K(t,function(M,L,N){J(M,L);E(L);E(N)})}
  function A (line 1) | function A(t){if(tinymce.inArray(s,t)!==-1){return}if(t.parentNode.tagNa...
  function x (line 1) | function x(M){var O,N,L,t;if(tinymce.inArray(s,M)!==-1){return}M=c(M,I);...
  function s (line 1) | function s(z){var y=w.create("li",{style:"list-style-type: none;"});w.in...
  function t (line 1) | function t(B){var y=s(B),D=w.getParent(B,"ol,ul"),C=D.tagName,E=w.getSty...
  function v (line 1) | function v(z){if(!d(u,z,x)){z=c(z,w);var y=t(z);y.appendChild(z);m(y.par...
  function A (line 1) | function A(t){var C,B,D;if(!d(u,t,s)){if(z.getStyle(t,"margin-left")!=="...
  function B (line 1) | function B(t){var s=tinymce.grep(t.childNodes,function(H){return !(H.nod...
  function x (line 1) | function x(s){z.removeClass(s,"_mce_act_on");if(!s||s.nodeType!==1||!y.p...
  function v (line 1) | function v(s){F.splitSafeEach(s.childNodes,x,true)}
  function C (line 1) | function C(s,t){return t>=0&&s.hasChildNodes()&&t<s.childNodes.length&&s...
  function D (line 1) | function D(){var t=w.getNode();var s=z.getParent(t,"td");return s!==null}

FILE: static/js/tinymce/plugins/lists/editor_plugin_src.js
  function skipWhitespaceNodes (line 15) | function skipWhitespaceNodes(e, next) {
  function skipWhitespaceNodesBackwards (line 22) | function skipWhitespaceNodesBackwards(e) {
  function skipWhitespaceNodesForwards (line 28) | function skipWhitespaceNodesForwards(e) {
  function hasParentInList (line 34) | function hasParentInList(ed, e, list) {
  function isList (line 40) | function isList(e) {
  function splitNestedLists (line 44) | function splitNestedLists(element, dom) {
  function attemptMergeWithAdjacent (line 62) | function attemptMergeWithAdjacent(e, allowDifferentListStyles, mergePara...
  function attemptMergeWithPrevious (line 67) | function attemptMergeWithPrevious(e, allowDifferentListStyles, mergePara...
  function attemptMergeWithNext (line 76) | function attemptMergeWithNext(e, allowDifferentListStyles, mergeParagrap...
  function attemptMerge (line 85) | function attemptMerge(e1, e2, differentStylesMasterElement, mergeParagra...
  function canMerge (line 95) | function canMerge(e1, e2, allowDifferentListStyles, mergeParagraphs) {
  function isListForIndent (line 105) | function isListForIndent(e) {
  function containsOnlyAList (line 110) | function containsOnlyAList(e) {
  function merge (line 115) | function merge(e1, e2, masterElement) {
  function findItemToOperateOn (line 131) | function findItemToOperateOn(e, dom) {
  function isTabInList (line 151) | function isTabInList(e) {
  function isOnLastListItem (line 157) | function isOnLastListItem() {
  function isNestedList (line 164) | function isNestedList(grandParent) {
  function isInEmptyListItem (line 172) | function isInEmptyListItem() {
  function getLi (line 176) | function getLi() {
  function isEmptyListItem (line 182) | function isEmptyListItem(li) {
  function isEmptyIE9Li (line 190) | function isEmptyIE9Li(li) {
  function isEnter (line 198) | function isEnter(e) {
  function isEnterWithoutShift (line 202) | function isEnterWithoutShift(e) {
  function getListKeyState (line 206) | function getListKeyState(e) {
  function cancelDefaultEvents (line 220) | function cancelDefaultEvents(ed, e) {
  function isCursorAtEndOfContainer (line 227) | function isCursorAtEndOfContainer() {
  function isEndOfListItem (line 248) | function isEndOfListItem() {
  function createNewLi (line 256) | function createNewLi(ed, e) {
  function imageJoiningListItem (line 275) | function imageJoiningListItem(ed, e) {
  function setCursorPositionToOriginalLi (line 344) | function setCursorPositionToOriginalLi(li) {
  function hasStyleIndent (line 369) | function hasStyleIndent(n) {
  function fixListItem (line 409) | function fixListItem(parent, reference) {
  function fixIndentedListItemForGecko (line 419) | function fixIndentedListItemForGecko(ed, e) {
  function fixIndentedListItemForIE8 (line 432) | function fixIndentedListItemForIE8(ed, e) {
  function fixDeletingFirstCharOfList (line 442) | function fixDeletingFirstCharOfList(ed, e) {
  function fixDeletingEmptyLiInWebkit (line 470) | function fixDeletingEmptyLiInWebkit(ed, e) {
  function cleanupBr (line 511) | function cleanupBr(e) {
  function makeList (line 517) | function makeList(element) {
  function doWrapList (line 557) | function doWrapList(start, end, template) {
  function processBrs (line 584) | function processBrs(element, callback) {
  function wrapList (line 643) | function wrapList(element) {
  function changeList (line 652) | function changeList(element) {
  function convertListItemToParagraph (line 664) | function convertListItemToParagraph(element) {
  function createWrapItem (line 737) | function createWrapItem(element) {
  function createWrapList (line 743) | function createWrapList(element) {
  function indentLI (line 758) | function indentLI(element) {
  function outdentLI (line 780) | function outdentLI(element) {
  function isEmptyElement (line 822) | function isEmptyElement(element) {
  function processElement (line 830) | function processElement(element) {
  function recurse (line 843) | function recurse(element) {
  function brAtEdgeOfSelection (line 847) | function brAtEdgeOfSelection(container, offset) {
  function isInTable (line 852) | function isInTable() {

FILE: static/js/tinymce/plugins/media/editor_plugin.js
  function e (line 1) | function e(j){return typeof(j)=="string"?j.replace(/[^0-9%]/g,""):j}
  function c (line 1) | function c(m){var l,j,k;if(m&&!m.splice){j=[];for(k=0;true;k++){if(m[k])...
  function o (line 1) | function o(s){return s&&s.nodeName==="IMG"&&n.dom.hasClass(s,"mceItemMed...
  function r (line 1) | function r(n,J){var N,M,O,L,K;K=p.getParam("flash_video_player_url",u.co...
  function u (line 1) | function u(O){return new tinymce.html.Serializer({inner:true,validate:fa...
  function J (line 1) | function J(P,O){return H[(P.attr(O)||"").toLowerCase()]}
  function p (line 1) | function p(P){var O=P.replace(/^.*\.([^.]+)$/,"$1");return H[O.toLowerCa...

FILE: static/js/tinymce/plugins/media/editor_plugin_src.js
  function normalizeSize (line 31) | function normalizeSize(size) {
  function toArray (line 35) | function toArray(obj) {
  function isMediaImg (line 58) | function isMediaImg(node) {
  function addPlayer (line 338) | function addPlayer(video_src, poster_src) {
  function getInnerHTML (line 660) | function getInnerHTML(node) {
  function lookupAttribute (line 667) | function lookupAttribute(o, attr) {
  function lookupExtension (line 671) | function lookupExtension(src) {

FILE: static/js/tinymce/plugins/media/js/embed.js
  function writeFlash (line 5) | function writeFlash(p) {
  function writeShockWave (line 14) | function writeShockWave(p) {
  function writeQuickTime (line 23) | function writeQuickTime(p) {
  function writeRealMedia (line 32) | function writeRealMedia(p) {
  function writeWindowsMedia (line 41) | function writeWindowsMedia(p) {
  function writeEmbed (line 51) | function writeEmbed(cls, cb, mt, p) {

FILE: static/js/tinymce/plugins/media/js/media.js
  function get (line 7) | function get(id) {
  function clone (line 11) | function clone(obj) {
  function getVal (line 38) | function getVal(id) {
  function setVal (line 50) | function setVal(id, value, name) {
  function parseQueryParams (line 155) | function parseQueryParams(str) {
  function setOptions (line 169) | function setOptions(type, names) {
  function option (line 473) | function option(media_type, element) {

FILE: static/js/tinymce/plugins/noneditable/editor_plugin.js
  function b (line 1) | function b(n){var j=n.dom,p=n.selection,r,o="mce_noneditablecaret",r="\u...
  function f (line 1) | function f(m,n){var o=j.length,p=n.content,l=tinymce.trim(g);if(n.format...

FILE: static/js/tinymce/plugins/noneditable/editor_plugin_src.js
  function handleContentEditableSelection (line 16) | function handleContentEditableSelection(ed) {
  function convertRegExpsToNonEditable (line 435) | function convertRegExpsToNonEditable(ed, args) {

FILE: static/js/tinymce/plugins/paste/editor_plugin.js
  function b (line 1) | function b(d,e){return d.getParam(e,a[e])}
  function h (line 1) | function h(l,j){var k=d.dom,i;f.onPreProcess.dispatch(f,l);l.node=k.crea...
  function g (line 1) | function g(s){var l,p,j,t,k=d.selection,o=d.dom,q=d.getBody(),i,r;if(s.c...
  function d (line 1) | function d(h){c(h,function(o){if(o.constructor==RegExp){j=j.replace(o,""...
  function x (line 1) | function x(A){return A+((A!=="0")&&(/\d$/.test(A)))?"px":""}
  function m (line 1) | function m(q,o){if(i==="all"){return""}var h=p(n(o.replace(/^(["'])(.*)\...
  function e (line 1) | function e(m){c(m,function(n){if(n.constructor==RegExp){j=j.replace(n,""...

FILE: static/js/tinymce/plugins/paste/editor_plugin_src.js
  function getParam (line 39) | function getParam(ed, name) {
  function process (line 79) | function process(o, force_rich) {
  function grabContent (line 150) | function grabContent(e) {
  function process (line 348) | function process(items) {
  function ensureUnits (line 446) | function ensureUnits(v) {
  function removeClasses (line 556) | function removeClasses(match, g1) {
  function process (line 766) | function process(items) {

FILE: static/js/tinymce/plugins/preview/jscripts/embed.js
  function writeFlash (line 5) | function writeFlash(p) {
  function writeShockWave (line 14) | function writeShockWave(p) {
  function writeQuickTime (line 23) | function writeQuickTime(p) {
  function writeRealMedia (line 32) | function writeRealMedia(p) {
  function writeWindowsMedia (line 41) | function writeWindowsMedia(p) {
  function writeEmbed (line 51) | function writeEmbed(cls, cb, mt, p) {

FILE: static/js/tinymce/plugins/searchreplace/editor_plugin.js
  function b (line 1) | function b(d){window.focus();a.windowManager.open({file:c+"/searchreplac...

FILE: static/js/tinymce/plugins/searchreplace/editor_plugin_src.js
  function open (line 14) | function open(m) {

FILE: static/js/tinymce/plugins/searchreplace/js/searchreplace.js
  function fix (line 56) | function fix() {
  function replace (line 64) | function replace() {

FILE: static/js/tinymce/plugins/style/js/props.js
  function aggregateStyles (line 30) | function aggregateStyles(allStyles) {
  function init (line 57) | function init(ed) {
  function setupFormData (line 158) | function setupFormData() {
  function getMeasurement (line 278) | function getMeasurement(s) {
  function getNum (line 282) | function getNum(s) {
  function inStr (line 289) | function inStr(s, n) {
  function getVal (line 293) | function getVal(s, i) {
  function setValue (line 302) | function setValue(f, n, v) {
  function setupBox (line 309) | function setupBox(f, ce, fp, pr, sf, b) {
  function isSame (line 359) | function isSame(e, pr, sf, b) {
  function hasEqualValues (line 386) | function hasEqualValues(a) {
  function toggleApplyAction (line 402) | function toggleApplyAction() {
  function applyAction (line 406) | function applyAction() {
  function updateAction (line 439) | function updateAction() {
  function generateCSS (line 444) | function generateCSS() {
  function isNum (line 604) | function isNum(s) {
  function showDisabledControls (line 608) | function showDisabledControls() {
  function fillSelect (line 621) | function fillSelect(f, s, param, dval, sep, em) {
  function toggleSame (line 655) | function toggleSame(ce, pre) {
  function synch (line 687) | function synch(fr, to) {
  function updateTextDecorations (line 696) | function updateTextDecorations(){

FILE: static/js/tinymce/plugins/tabfocus/editor_plugin.js
  function e (line 1) | function e(i,j){if(j.keyCode===9){return a.cancel(j)}}
  function h (line 1) | function h(l,p){var j,m,o,n,k;function q(t){n=c.select(":input:enabled,*...

FILE: static/js/tinymce/plugins/tabfocus/editor_plugin_src.js
  function tabCancel (line 16) | function tabCancel(ed, e) {
  function tabHandler (line 21) | function tabHandler(ed, e) {

FILE: static/js/tinymce/plugins/table/editor_plugin.js
  function c (line 1) | function c(g,h){var j=h.ownerDocument,f=j.createRange(),k;f.setStartBefo...
  function a (line 1) | function a(g,f){return parseInt(g.getAttribute(f)||1)}
  function b (line 1) | function b(H,G,K){var g,L,D,o;t();o=G.getParent(K.getStart(),"th,td");if...
  function l (line 1) | function l(p){var o=g.selection,n=g.dom.getParent(p||o.getNode(),"table"...
  function k (line 1) | function k(){g.getBody().style.webkitUserSelect="";if(j){g.dom.removeCla...
  function D (line 1) | function D(J,L){var K=new d.dom.TreeWalker(J,J);do{if(J.nodeType==3&&d.t...
  function o (line 1) | function o(D,z,A,F){var B=3,G=D.dom.getParent(z.startContainer,"TABLE"),...
  function n (line 1) | function n(A){if(!d.isWebKit){return}var z=A.selection.getRng();var C=A....
  function v (line 1) | function v(C,N){var L=d.VK;var Q=N.keyCode;function O(Y,U,S){var T=Y?"pr...
  function s (line 1) | function s(){var w;for(w=r.getBody().lastChild;w&&w.nodeType==3&&!w.node...

FILE: static/js/tinymce/plugins/table/editor_plugin_src.js
  function isAtStart (line 15) | function isAtStart(rng, par) {
  function getSpanVal (line 28) | function getSpanVal(td, name) {
  function TableGrid (line 35) | function TableGrid(table, dom, selection) {
  function createTableGrid (line 779) | function createTableGrid(node) {
  function cleanup (line 786) | function cleanup() {
  function setPoint (line 929) | function setPoint(node, start) {
  function tableCellSelected (line 999) | function tableCellSelected(ed, rng, n, currentCell) {
  function fixTableCellSelection (line 1019) | function fixTableCellSelection(ed) {
  function moveSelection (line 1098) | function moveSelection(ed, e) {
  function fixTableCaretPos (line 1244) | function fixTableCaretPos() {

FILE: static/js/tinymce/plugins/table/js/cell.js
  function init (line 5) | function init() {
  function updateAction (line 63) | function updateAction() {
  function nextCell (line 184) | function nextCell(elm) {
  function updateCell (line 193) | function updateCell(td, skip_id) {
  function changedBackgroundImage (line 255) | function changedBackgroundImage() {
  function changedSize (line 264) | function changedSize() {
  function changedColor (line 283) | function changedColor() {
  function changedStyle (line 293) | function changedStyle() {

FILE: static/js/tinymce/plugins/table/js/row.js
  function init (line 3) | function init() {
  function updateAction (line 56) | function updateAction() {
  function updateRow (line 120) | function updateRow(tr_elm, skip_id, skip_parent) {
  function changedBackgroundImage (line 189) | function changedBackgroundImage() {
  function changedStyle (line 198) | function changedStyle() {
  function changedSize (line 216) | function changedSize() {
  function changedColor (line 229) | function changedColor() {
  function changedRowType (line 238) | function changedRowType() {
  function setActionforRowType (line 246) | function setActionforRowType(formObj, rowtype) {

FILE: static/js/tinymce/plugins/table/js/table.js
  function insertTable (line 5) | function insertTable() {
  function makeAttrib (line 272) | function makeAttrib(attrib, value) {
  function init (line 295) | function init() {
  function changedSize (line 399) | function changedSize() {
  function isCssSize (line 418) | function isCssSize(value) {
  function cssSize (line 422) | function cssSize(value, def) {
  function changedBackgroundImage (line 432) | function changedBackgroundImage() {
  function changedBorder (line 441) | function changedBorder() {
  function changedColor (line 458) | function changedColor() {
  function changedStyle (line 475) | function changedStyle() {

FILE: static/js/tinymce/plugins/template/editor_plugin.js
  function e (line 1) | function e(l,h){return new RegExp("\\b"+h+"\\b","g").test(l.className)}
  function c (line 1) | function c(g,d){var f;g=""+g;if(g.length<d){for(f=0;f<(d-g.length);f++){...

FILE: static/js/tinymce/plugins/template/editor_plugin_src.js
  function hasClass (line 82) | function hasClass(n, c) {
  function addZeros (line 123) | function addZeros(value, len) {

FILE: static/js/tinymce/plugins/template/js/template.js
  function g (line 83) | function g(s) {

FILE: static/js/tinymce/plugins/wordcount/editor_plugin.js
  function b (line 1) | function b(h){return h!==f&&(h===g.ENTER||f===g.SPACEBAR||a(f))}
  function a (line 1) | function a(h){return h===g.DELETE||h===g.BACKSPACE}

FILE: static/js/tinymce/plugins/wordcount/editor_plugin_src.js
  function checkKeys (line 54) | function checkKeys(key) {
  function checkDelOrBksp (line 58) | function checkDelOrBksp(key) {

FILE: static/js/tinymce/plugins/xhtmlxtras/js/abbr.js
  function init (line 11) | function init() {
  function insertAbbr (line 18) | function insertAbbr() {
  function removeAbbr (line 23) | function removeAbbr() {

FILE: static/js/tinymce/plugins/xhtmlxtras/js/acronym.js
  function init (line 11) | function init() {
  function insertAcronym (line 18) | function insertAcronym() {
  function removeAcronym (line 23) | function removeAcronym() {

FILE: static/js/tinymce/plugins/xhtmlxtras/js/attributes.js
  function init (line 11) | function init() {
  function setFormValue (line 46) | function setFormValue(name, value) {
  function insertAction (line 52) | function insertAction() {
  function setAttrib (line 61) | function setAttrib(elm, attrib, value) {
  function setAllAttribs (line 77) | function setAllAttribs(elm) {
  function insertAttribute (line 106) | function insertAttribute() {

FILE: static/js/tinymce/plugins/xhtmlxtras/js/cite.js
  function init (line 11) | function init() {
  function insertCite (line 18) | function insertCite() {
  function removeCite (line 23) | function removeCite() {

FILE: static/js/tinymce/plugins/xhtmlxtras/js/del.js
  function init (line 11) | function init() {
  function setElementAttribs (line 20) | function setElementAttribs(elm) {
  function insertDel (line 27) | function insertDel() {
  function removeDel (line 48) | function removeDel() {

FILE: static/js/tinymce/plugins/xhtmlxtras/js/element_common.js
  function initCommonAttributes (line 13) | function initCommonAttributes(elm) {
  function setFormValue (line 37) | function setFormValue(name, value) {
  function insertDateTime (line 41) | function insertDateTime(id) {
  function getDateTime (line 45) | function getDateTime(d, fmt) {
  function addZeros (line 62) | function addZeros(value, len) {
  function selectByValue (line 75) | function selectByValue(form_obj, field_name, value, add_custom, ignore_c...
  function setAttrib (line 101) | function setAttrib(elm, attrib, value) {
  function setAllCommonAttribs (line 107) | function setAllCommonAttribs(elm) {
  function insertInlineElement (line 221) | function insertInlineElement(en) {

FILE: static/js/tinymce/plugins/xhtmlxtras/js/ins.js
  function init (line 11) | function init() {
  function setElementAttribs (line 20) | function setElementAttribs(elm) {
  function insertIns (line 27) | function insertIns() {
  function removeIns (line 48) | function removeIns() {

FILE: static/js/tinymce/themes/advanced/editor_template.js
  function b (line 1) | function b(p,m){var k,l,o=p.dom,j="",n,r;previewStyles=p.settings.previe...
  function z (line 1) | function z(H){H.preventDefault();n=B+(H.screenX-D);F=G+(H.screenY-A);w.r...
  function C (line 1) | function C(H){g.remove(i.doc,"mousemove",t);g.remove(q.getDoc(),"mousemo...
  function q (line 1) | function q(p){var s,n=F.parents,t=p;if(typeof(p)=="string"){t=function(v...
  function B (line 1) | function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==...
  function B (line 1) | function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==...

FILE: static/js/tinymce/themes/advanced/editor_template_src.js
  function getPreviewCss (line 15) | function getPreviewCss(ed, fmt) {
  function resizeOnMove (line 1023) | function resizeOnMove(e) {
  function endResize (line 1032) | function endResize(e) {
  function getParent (line 1082) | function getParent(name) {
  function updateColor (line 1190) | function updateColor(controlId, color) {
  function updateColor (line 1204) | function updateColor(controlId, color) {

FILE: static/js/tinymce/themes/advanced/js/about.js
  function init (line 3) | function init() {
  function insertHelpIFrame (line 62) | function insertHelpIFrame() {

FILE: static/js/tinymce/themes/advanced/js/charmap.js
  function addKeyboardNavigation (line 281) | function addKeyboardNavigation(){
  function renderCharMapHTML (line 302) | function renderCharMapHTML() {
  function insertChar (line 337) | function insertChar(chr) {
  function previewChar (line 348) | function previewChar(codeA, codeB, codeN) {

FILE: static/js/tinymce/themes/advanced/js/color_picker.js
  function init (line 63) | function init() {
  function toHexColor (line 87) | function toHexColor(color) {
  function insertAction (line 129) | function insertAction() {
  function showColor (line 148) | function showColor(color, name) {
  function convertRGBToHex (line 156) | function convertRGBToHex(col) {
  function convertHexToRGB (line 178) | function convertHexToRGB(col) {
  function generatePicker (line 192) | function generatePicker() {
  function generateWebColors (line 209) | function generateWebColors() {
  function paintCanvas (line 240) | function paintCanvas(el) {
  function generateNamedColors (line 249) | function generateNamedColors() {
  function enableKeyboardNavigation (line 273) | function enableKeyboardNavigation(el) {
  function dechex (line 280) | function dechex(n) {
  function computeColor (line 284) | function computeColor(e) {
  function updateLight (line 307) | function updateLight(r, g, b) {
  function changeFinalColor (line 329) | function changeFinalColor(color) {
  function setCol (line 337) | function setCol(e, c) {

FILE: static/js/tinymce/themes/advanced/js/source_editor.js
  function saveContent (line 4) | function saveContent() {
  function onLoadInit (line 9) | function onLoadInit() {
  function setWrap (line 26) | function setWrap(val) {
  function setWhiteSpaceCss (line 40) | function setWhiteSpaceCss(value) {
  function turnWrapOff (line 45) | function turnWrapOff() {
  function turnWrapOn (line 53) | function turnWrapOn() {
  function toggleWordWrap (line 61) | function toggleWordWrap(elm) {
  function resizeInputs (line 69) | function resizeInputs() {

FILE: static/js/tinymce/tiny_mce.js
  function h (line 1) | function h(i){if(i.src&&/tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|...
  function k (line 1) | function k(){var l=document;function f(){l.detachEvent("onstop",f);if(g)...
  function h (line 1) | function h(m,n){var l=this;if(n){l.removeAttr("data-mce-style")}return i...
  function g (line 1) | function g(m,n){var l=this;if(b.test(m)){if(n!==c){l.each(function(o,p){...
  function k (line 1) | function k(l){if(l.css!==h){l.css=h;l.attr=g;l.tinymce=j;l.pushStack=fun...
  function serialize (line 1) | function serialize(o,quote){var i,v,t,name;quote=quote||'"';if(o==null){...
  function f (line 1) | function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10...
  function d (line 1) | function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}
  function A (line 1) | function A(N,M){try{a.getDoc().execCommand(N,false,M)}catch(L){}}
  function n (line 1) | function n(){var L=a.getDoc().documentMode;return L?L:6}
  function z (line 1) | function z(L){return L.isDefaultPrevented()}
  function J (line 1) | function J(){function L(O){var M,Q,N,P;M=l.getRng();Q=e.getParent(M.star...
  function q (line 1) | function q(){function L(O){var N=e.create("body");var P=O.cloneContents(...
  function I (line 1) | function I(){a.onKeyDown.add(function(L,M){if(!z(M)&&M.keyCode==65&&j.me...
  function K (line 1) | function K(){if(!a.settings.content_editable){e.bind(a.getDoc(),"focusin...
  function B (line 1) | function B(){a.onKeyDown.add(function(L,O){if(!z(O)&&O.keyCode===f){if(l...
  function y (line 1) | function y(){if(!Range.prototype.getClientRects){a.onMouseDown.add(funct...
  function h (line 1) | function h(){a.onClick.add(function(L,M){M=M.target;if(/^(IMG|HR)$/.test...
  function c (line 1) | function c(){function M(){var O=e.getAttribs(l.getStart().cloneNode(fals...
  function b (line 1) | function b(){var M,L;e.bind(a.getDoc(),"selectionchange",function(){if(L...
  function x (line 1) | function x(){document.body.setAttribute("role","application")}
  function t (line 1) | function t(){a.onKeyDown.add(function(L,N){if(!z(N)&&N.keyCode===f){if(l...
  function C (line 1) | function C(){if(n()>7){return}A("RespectVisibilityInDesign",true);a.cont...
  function g (line 1) | function g(){e.bind(a.getBody(),"mouseup",function(N){var M,L=l.getNode(...
  function d (line 1) | function d(){a.onKeyDown.add(function(R,S){var Q,L,M,O,P,T,N;Q=S.keyCode...
  function G (line 1) | function G(){a.onKeyDown.add(function(P,Q){var N,M,R,L,O;if(z(Q)||Q.keyC...
  function F (line 1) | function F(){function L(){a._refreshContentEditable();A("StyleWithCSS",f...
  function s (line 1) | function s(){function L(M,N){E(e.select("a"),function(Q){var O=Q.parentN...
  function m (line 1) | function m(){if(H.forced_root_block){a.onInit.add(function(){A("DefaultP...
  function p (line 1) | function p(){function L(N,M){if(!N||!M.initial){a.execCommand("mceRepain...
  function i (line 1) | function i(){a.onKeyDown.add(function(M,N){var L;if(!z(N)&&N.keyCode==f)...
  function r (line 1) | function r(){var L;if(n()>=10){L="";E("p div h1 h2 h3 h4 h5 h6".split(" ...
  function u (line 1) | function u(){var N,M,ad,L,Y,ab,Z,ac,O,P,aa,W,V,X=document,T=a.getDoc();i...
  function D (line 1) | function D(){if(n()<9){v.addNodeFilter("noscript",function(L){var M=L.le...
  function h (line 1) | function h(l){var m;m=document.createElement("div");m.innerHTML=l;return...
  function e (line 1) | function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n<m....
  function m (line 1) | function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&...
  function n (line 1) | function n(r,q){return p.encodeNamed(r,q,o)}
  function c (line 1) | function c(n,q,p,i){function o(r){r=parseInt(r).toString(16);return r.le...
  function p (line 1) | function p(D,G){var F,C,B,E;F=z[D+"-top"+G];if(!F){return}C=z[D+"-right"...
  function u (line 1) | function u(C){var D=z[C],B;if(!D||D.indexOf(" ")<0){return}D=D.split(" "...
  function A (line 1) | function A(D,C,B,E){if(!u(C)){return}if(!u(B)){return}if(!u(E)){return}z...
  function t (line 1) | function t(B){r=true;return a[B]}
  function i (line 1) | function i(C,B){if(r){C=C.replace(/\uFEFF[0-9]/g,function(D){return a[D]...
  function o (line 1) | function o(C,B,F,E,G,D){G=G||D;if(G){G=i(G);return"'"+G.replace(/\'/g,"\...
  function i (line 1) | function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u<s;u++...
  function d (line 1) | function d(j,i){return j.split(i||",")}
  function h (line 1) | function h(m,l){var j,k={};function i(n){return n.replace(/[A-Z]+/g,func...
  function b (line 1) | function b(){var i=a.html5;if(!i){i=a.html5=h({A:"id|accesskey|class|dir...
  function c (line 1) | function c(){var i=a.html4;if(!i){i=a.html4=h({Z:"H|K|N|O|P",Y:"X|form|R...
  function m (line 1) | function m(F,E,H){var G=A[F];if(!G){G=a[F];if(!G){G=e(E," ",e(E.toUpperC...
  function i (line 1) | function i(E){return new RegExp("^"+E.replace(/([?+*])/g,".$1")+"$")}
  function C (line 1) | function C(L){var K,G,Z,V,aa,F,I,U,X,Q,Y,ac,O,J,W,E,S,H,ab,ad,P,T,N=/^([...
  function t (line 1) | function t(E){s={};j=[];C(E);g(y,function(G,F){k[F]=G.children})}
  function l (line 1) | function l(F){var E=/^(~)?(.+)$/;if(F){g(d(F),function(J){var H=E.exec(J...
  function x (line 1) | function x(F){var E=/^([+\-]?)(\w+)\[([^\]]+)\]$/;if(F){g(d(F),function(...
  function B (line 1) | function B(E){var G=s[E],F;if(G){return G}F=j.length;while(F--){G=j[F];i...
  function u (line 1) | function u(T){var V,U;V=A.length;while(V--){if(A[V].name===T){break}}if(...
  function p (line 1) | function p(U,T,Y,X,W){var Z,V;T=T.toLowerCase();Y=T in H?T:j(Y||X||W||""...
  function a (line 1) | function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next"...
  function b (line 1) | function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];thi...
  function j (line 1) | function j(n){var p,q,y,x,A,o,r,l,u,v,k,t,m,z,s;t=b.makeMap("tr,td,th,tb...
  function G (line 1) | function G(){var O=J.firstChild,l,P;while(O){l=O.next;if(O.type==3||(O.t...
  function K (line 1) | function K(l,O){var P=new a(l,O),Q;if(l in e){Q=i[l];if(Q){Q.push(P)}els...
  function I (line 1) | function I(P){var Q,l,O;for(Q=P.prev;Q&&Q.type===3;){l=Q.value.replace(t...
  function H (line 1) | function H(O){var P,l={};for(P in O){if(P!=="li"&&P!="p"){l[P]=O[P]}}ret...
  function f (line 1) | function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shor...
  function c (line 1) | function c(k,j,l,i){if(k.addEventListener){k.addEventListener(j,l,i||fal...
  function e (line 1) | function e(k,j,l,i){if(k.removeEventListener){k.removeEventListener(j,l,...
  function a (line 1) | function a(n,l){var i,k=l||{};function j(){return false}function m(){ret...
  function d (line 1) | function d(m,n,l){var k=m.document,j={type:"ready"};function i(){if(!l.d...
  function f (line 1) | function f(k){var q=this,p={},i,o,n,m,l;m="onmouseenter" in document.doc...
  function d (line 1) | function d(i,f,e,j){var h,g;if(i){if(!j&&i[f]){return i[f]}if(i!=c){h=i[...
  function k (line 1) | function k(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.la...
  function j (line 1) | function j(l){l=parseInt(l,10).toString(16);return l.length>1?l:"0"+l}
  function q (line 1) | function q(i){g(i.imports,function(s){q(s)});g(i.cssRules||i.rules,funct...
  function j (line 1) | function j(v){var t,s=v.childNodes,u=v.nodeType;function x(A){var z=A.pr...
  function b (line 1) | function b(c){var O=this,e=c.doc,U=0,F=1,j=2,E=true,S=false,W="startOffs...
  function a (line 1) | function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=...
  function f (line 1) | function f(g){return g.replace(/[\n\r]+/g,"")}
  function g (line 1) | function g(z,A){var t=0;e(n.select(z),function(C,B){if(C==A){t=B}});retu...
  function u (line 1) | function u(t){function z(E){var A,D,C,B=E?"start":"end";A=t[B+"Container...
  function l (line 1) | function l(){var z=y.getRng(true),t=n.getRoot(),A={};function B(E,J){var...
  function h (line 1) | function h(A){var t=o[A?"start":"end"],x,y,z,v;if(t){z=t[0];for(y=r,x=t....
  function l (line 1) | function l(B){var v=m.get(o.id+"_"+B),A,t,y,z,x=o.keep;if(v){A=v.parentN...
  function n (line 1) | function n(t){if(m.isBlock(t)&&!t.innerHTML&&!b){t.innerHTML='<br data-m...
  function i (line 1) | function i(n,p){var o=new a(n,n);do{if(n.nodeType==3&&d.trim(n.nodeValue...
  function k (line 1) | function k(q,o){var p=q;while(q&&q.nodeType===3&&q.length===0){q=o?q.nex...
  function k (line 1) | function k(p){var o,r,n,s=h.dom,u=s.getRoot(),q,t,v;function y(z,A){var ...
  function j (line 1) | function j(p,s){var q=i.createTextRange();try{q.moveToPoint(p,s)}catch(r...
  function m (line 1) | function m(q){var p;if(q.button){p=j(q.x,q.y);if(p){if(p.compareEndPoint...
  function l (line 1) | function l(){var p=n.selection.createRange();if(o&&!p.item&&p.compareEnd...
  function j (line 1) | function j(p){return p.replace(/(<!--\[CDATA\[|\]\]-->)/g,"\n").replace(...
  function b (line 1) | function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s...
  function n (line 1) | function n(r){a.each(e[r],function(s){s.func.call(s.scope)});e[r]=f}
  function f (line 1) | function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.leng...
  function p (line 1) | function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}
  function n (line 1) | function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}
  function k (line 1) | function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.pa...
  function f (line 1) | function f(j,k){return j.splitText(k)}
  function g (line 1) | function g(l){var k=h.items[l.target.selectedIndex-1];if(k&&(k=k.value))...
  function i (line 1) | function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.create...
  function q (line 1) | function q(t){var s=t.id;if(!s){s=t.name;if(s&&!k.get(s)){s=t.name}else{...
  function m (line 1) | function m(z,A,t){var y=z[A];if(!y){return}if(j.is(y,"string")){t=y.repl...
  function p (line 1) | function p(t,s){return s.constructor===RegExp?s.test(t.className):k.hasC...
  function m (line 1) | function m(){n.destroy();l.detachEvent("onunload",m);l=l.tinyMCE=l.tinym...
  function n (line 1) | function n(){if(q.language&&q.language_load!==false){m.add(k.baseURL+"/l...
  function A (line 1) | function A(s){var t=c.get(s),o=c.urls[s]||k.documentBaseURL.replace(/\/$...
  function c (line 1) | function c(i,m){var n=i.type;if(l.removed){return}if(l.onEvent.dispatch(...
  function j (line 1) | function j(i){l.focus(true)}
  function k (line 1) | function k(i,m){if(m.keyCode!=65||!a.VK.metaKeyPressed(m)){l.selection.n...
  function g (line 1) | function g(m,i){if(m.altKey||m.ctrlKey||m.metaKey){b(l.shortcuts,functio...
  function r (line 1) | function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);retur...
  function l (line 1) | function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}retur...
  function h (line 1) | function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}retur...
  function u (line 1) | function u(v,x){x=x||"exec";e(v,function(z,y){e(y.toLowerCase().split(",...
  function f (line 1) | function f(y,x,v){if(x===b){x=c}if(v===b){v=null}return n.getDoc().execC...
  function t (line 1) | function t(v){return q.match(v)}
  function s (line 1) | function s(v,x){q.toggle(v,x?{value:x}:b)}
  function i (line 1) | function i(v){o=p.getBookmark(v)}
  function g (line 1) | function g(){p.moveToBookmark(o)}
  function c (line 1) | function c(){return b.trim(h.getContent({format:"raw",no_events:1}).repl...
  function d (line 1) | function d(){l.typing=false;l.add()}
  function f (line 1) | function f(){var j=a.getStart(),h=c.getBody(),g,k,o,s,q,i,l,m=-16777215,...
  function g (line 1) | function g(o){return o.settings.use_accessible_selects&&!c.isGecko}
  function I (line 1) | function I(ab){return !!aa.schema.getTextBlocks()[ab.toLowerCase()]}
  function n (line 1) | function n(ac,ab){return c.getParents(ac,ab,c.getRoot())}
  function b (line 1) | function b(ab){return ab.nodeType===1&&ab.id==="_mce_caret"}
  function j (line 1) | function j(){l({alignleft:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,d...
  function W (line 1) | function W(){aa.addShortcut("ctrl+b","bold_desc","Bold");aa.addShortcut(...
  function V (line 1) | function V(ab){return ab?Q[ab]:Q}
  function l (line 1) | function l(ab,ac){if(ab){if(typeof(ab)!=="string"){T(ab,function(ae,ad){...
  function Y (line 1) | function Y(ae,al,ag){var ah=V(ae),am=ah[0],ak,ac,aj,ai=r.isCollapsed();f...
  function B (line 1) | function B(ad,am,af){var ag=V(ad),ao=ag[0],ak,aj,ac,al=true;function ae(...
  function F (line 1) | function F(ac,ae,ad){var ab=V(ac);if(k(ac,ae,ad)&&(!("toggle" in ab[0])|...
  function y (line 1) | function y(ac,ab,ah,af){var ad=V(ab),ai,ag,ae;function aj(an,ap,aq){var ...
  function k (line 1) | function k(ad,af,ae){var ac;function ab(ag){ag=c.getParent(ag,function(a...
  function v (line 1) | function v(ai,ah){var af,ag=[],ae={},ad,ac,ab;af=r.getStart();c.getParen...
  function z (line 1) | function z(af){var ah=V(af),ae,ad,ag,ac,ab;if(ah){ae=r.getStart();ad=n(a...
  function J (line 1) | function J(ab,ae,ac){var ad;if(!P){P={};ad={};aa.onNodeChange.addToTop(f...
  function h (line 1) | function h(ab,ac){if(g(ab,ac.inline)){return C}if(g(ab,ac.block)){return...
  function g (line 1) | function g(ac,ab){ac=ac||"";ab=ab||"";ac=""+(ac.nodeName||ac);ab=""+(ab....
  function O (line 1) | function O(ac,ab){var ad=c.getStyle(ac,ab);if(ab=="color"||ab=="backgrou...
  function q (line 1) | function q(ab,ac){if(typeof(ab)!="string"){ab=ab(ac)}else{if(ac){ab=ab.r...
  function f (line 1) | function f(ab){return ab&&ab.nodeType===3&&/^([\t \r\n]+|)$/.test(ab.nod...
  function S (line 1) | function S(ad,ac,ab){var ae=c.create(ac,ab);ad.parentNode.insertBefore(a...
  function p (line 1) | function p(ab,am,ae){var ap,an,ah,al,ad=ab.startContainer,ai=ab.startOff...
  function Z (line 1) | function Z(ah,ag,ae,ab){var ad,ac,af;if(!h(ae,ah)){return X}if(ah.remove...
  function o (line 1) | function o(ad,ae){var ab=ad.parentNode,ac;function af(ah,ag,ai){ah=E(ah,...
  function E (line 1) | function E(ac,ab,ad){if(ac){ab=ab?"nextSibling":"previousSibling";for(ac...
  function K (line 1) | function K(ab){return ab&&ab.nodeType==1&&ab.getAttribute("data-mce-type...
  function u (line 1) | function u(af,ae){var ab,ad,ac;function ah(ak,aj){if(ak.nodeName!=aj.nod...
  function I (line 1) | function I(ab){return/^(h[1-6]|p|div|pre|address|dl|dt|dd)$/.test(ab)}
  function M (line 1) | function M(ac,ag){var ab,af,ad,ae;ab=ac[ag?"startContainer":"endContaine...
  function U (line 1) | function U(ak,ab,ai){var al="_mce_caret",ac=aa.settings.caret_debug;func...
  function R (line 1) | function R(ac){var ab=ac.startContainer,ai=ac.startOffset,ae,ah,ag,ad,af...
  function b (line 1) | function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rena...
  function f (line 1) | function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("fo...
  function g (line 1) | function g(A){var v=e.getRng(true),G,j,z,u,p,M,B,o,k,n,t,J,x,C;function ...

FILE: static/js/tinymce/tiny_mce_popup.js
  function b (line 5) | function b(){a.editor.windowManager.close(window);tinymce=tinyMCE=a.edit...

FILE: static/js/tinymce/tiny_mce_src.js
  function getBase (line 64) | function getBase(n) {
  function fakeUnload (line 335) | function fakeUnload() {
  function css (line 473) | function css(name, value) {
  function attr (line 484) | function attr(name, value) {
  function patch (line 507) | function patch(jq) {
  function serialize (line 1150) | function serialize(o, quote) {
  function ready (line 1219) | function ready() {
  function get (line 1238) | function get(s) {
  function setEditorCommandState (line 1355) | function setEditorCommandState(cmd, state) {
  function getDocumentMode (line 1363) | function getDocumentMode() {
  function isDefaultPrevented (line 1369) | function isDefaultPrevented(e) {
  function cleanupStylesWhenDeleting (line 1373) | function cleanupStylesWhenDeleting() {
  function emptyEditorWhenDeleting (line 1439) | function emptyEditorWhenDeleting() {
  function selectAll (line 1487) | function selectAll() {
  function inputMethodFocus (line 1496) | function inputMethodFocus() {
  function removeHrOnBackspace (line 1513) | function removeHrOnBackspace() {
  function focusBody (line 1529) | function focusBody() {
  function selectControlElements (line 1549) | function selectControlElements() {
  function removeStylesWhenDeletingAccrossBlockElements (line 1568) | function removeStylesWhenDeletingAccrossBlockElements() {
  function selectionChangeNodeChanged (line 1621) | function selectionChangeNodeChanged() {
  function ensureBodyHasRoleApplication (line 1642) | function ensureBodyHasRoleApplication() {
  function disableBackspaceIntoATable (line 1646) | function disableBackspaceIntoATable() {
  function addNewLinesBeforeBrInPre (line 1659) | function addNewLinesBeforeBrInPre() {
  function removePreSerializedStylesWhenSelectingControls (line 1710) | function removePreSerializedStylesWhenSelectingControls() {
  function keepInlineElementOnDeleteBackspace (line 1731) | function keepInlineElementOnDeleteBackspace() {
  function removeBlockQuoteOnBackSpace (line 1771) | function removeBlockQuoteOnBackSpace() {
  function setGeckoEditingOptions (line 1808) | function setGeckoEditingOptions() {
  function addBrAfterLastLinks (line 1826) | function addBrAfterLastLinks() {
  function setDefaultBlockType (line 1854) | function setDefaultBlockType() {
  function removeGhostSelection (line 1862) | function removeGhostSelection() {
  function deleteControlItemOnBackSpace (line 1874) | function deleteControlItemOnBackSpace() {
  function renderEmptyBlocksFix (line 1890) | function renderEmptyBlocksFix() {
  function fakeImageResize (line 1904) | function fakeImageResize() {
  function keepNoScriptContents (line 2137) | function keepNoScriptContents() {
  function nativeDecode (line 2258) | function nativeDecode(text) {
  function buildEntitiesLookup (line 2268) | function buildEntitiesLookup(items, radix) {
  function encodeNamedAndNumeric (line 2357) | function encodeNamedAndNumeric(text, attr) {
  function encodeCustomNamed (line 2363) | function encodeCustomNamed(text, attr) {
  function toHex (line 2427) | function toHex(match, r, g, b) {
  function compress (line 2445) | function compress(prefix, suffix) {
  function canCompress (line 2473) | function canCompress(key) {
  function compress2 (line 2491) | function compress2(target, a, b, c) {
  function encode (line 2509) | function encode(str) {
  function decode (line 2517) | function decode(str, keep_slashes) {
  function processUrl (line 2530) | function processUrl(match, url, url2, url3, str, str2) {
  function serializeStyles (line 2599) | function serializeStyles(name) {
  function split (line 2637) | function split(str, delim) {
  function unpack (line 2641) | function unpack(lookup, data) {
  function getHTML5 (line 2670) | function getHTML5() {
  function getHTML4 (line 2794) | function getHTML4() {
  function createLookupTable (line 2927) | function createLookupTable(option, default_value, extend) {
  function patternToRegExp (line 2977) | function patternToRegExp(str) {
  function addValidElements (line 2983) | function addValidElements(valid_elements) {
  function setValidElements (line 3122) | function setValidElements(valid_elements) {
  function addCustomElements (line 3134) | function addCustomElements(custom_elements) {
  function addValidChildren (line 3168) | function addValidChildren(valid_children) {
  function getElementRule (line 3197) | function getElementRule(name) {
  function processEndTag (line 3377) | function processEndTag(name) {
  function parseAttribute (line 3402) | function parseAttribute(match, name, value, val2, val3) {
  function walk (line 3657) | function walk(node, root_node, prev) {
  function Node (line 3681) | function Node(name, type) {
  function fixInvalidChildren (line 3990) | function fixInvalidChildren(nodes) {
  function addRootBlocks (line 4179) | function addRootBlocks() {
  function createNode (line 4201) | function createNode(name, type) {
  function removeWhitespaceBefore (line 4216) | function removeWhitespaceBefore(node) {
  function cloneAndExcludeBlocks (line 4233) | function cloneAndExcludeBlocks(input) {
  function walk (line 4755) | function walk(node) {
  function addEvent (line 4826) | function addEvent(target, name, callback, capture) {
  function removeEvent (line 4834) | function removeEvent(target, name, callback, capture) {
  function fix (line 4842) | function fix(original_event, data) {
  function bindOnReady (line 4912) | function bindOnReady(win, callback, event_utils) {
  function EventUtils (line 4962) | function EventUtils(proxy) {
  function findSibling (line 5367) | function findSibling(node, start_name, sibling_name, shallow) {
  function setHTML (line 6270) | function setHTML(e, h, d) {
  function hex (line 6391) | function hex(s) {
  function addClasses (line 6412) | function addClasses(s) {
  function trim (line 6623) | function trim(node) {
  function Range (line 6788) | function Range(dom) {
  function Selection (line 7492) | function Selection(selection) {
  function trimNl (line 8075) | function trimNl(s) {
  function findIndex (line 8319) | function findIndex(name, element) {
  function normalizeTableCellSelection (line 8330) | function normalizeTableCellSelection(rng) {
  function getLocation (line 8353) | function getLocation() {
  function setEndPoint (line 8469) | function setEndPoint(start) {
  function restoreEndPoint (line 8503) | function restoreEndPoint(suffix) {
  function addBogus (line 8565) | function addBogus(node) {
  function setPoint (line 8605) | function setPoint(node, start) {
  function skipEmptyTextNodes (line 8789) | function skipEmptyTextNodes(n, forwards) {
  function normalizeEndPoint (line 8892) | function normalizeEndPoint(start) {
  function rngFromPoint (line 9135) | function rngFromPoint(x, y) {
  function selectionChange (line 9149) | function selectionChange(e) {
  function endSelection (line 9171) | function endSelection() {
  function trim (line 9308) | function trim(value) {
  function loadScript (line 9498) | function loadScript(url, callback) {
  function execScriptLoadedCallbacks (line 9628) | function execScriptLoadedCallbacks(url) {
  function exclude (line 9714) | function exclude(nodes) {
  function collectSiblings (line 9732) | function collectSiblings(node, name, end_node) {
  function findEndPoint (line 9741) | function findEndPoint(node, root) {
  function walkBoundary (line 9750) | function walkBoundary(start_node, end_node, next) {
  function splitText (line 9826) | function splitText(node, offset) {
  function onChange (line 11108) | function onChange(e) {
  function loadDependencies (line 11726) | function loadDependencies() {
  function createId (line 11805) | function createId(elm) {
  function execCallback (line 11825) | function execCallback(se, n, s) {
  function hasClass (line 11840) | function hasClass(n, c) {
  function clr (line 12003) | function clr() {
  function loadScripts (line 12288) | function loadScripts() {
  function initPlugin (line 12345) | function initPlugin(p) {
  function eventHandler (line 13663) | function eventHandler(evt, args) {
  function doOperaFocus (line 13677) | function doOperaFocus(e) {
  function nodeChanged (line 13681) | function nodeChanged(ed, e) {
  function handleShortcut (line 13739) | function handleShortcut(e, execute) {
  function execCommand (line 13791) | function execCommand(command, ui, value) {
  function queryCommandState (line 13803) | function queryCommandState(command) {
  function queryCommandValue (line 13813) | function queryCommandValue(command) {
  function addCommands (line 13823) | function addCommands(command_list, type) {
  function execNativeCommand (line 13843) | function execNativeCommand(command, ui, value) {
  function isFormatMatch (line 13853) | function isFormatMatch(name) {
  function toggleFormat (line 13857) | function toggleFormat(name, value) {
  function storeSelection (line 13861) | function storeSelection(type) {
  function restoreSelection (line 13865) | function restoreSelection() {
  function getContent (line 14339) | function getContent() {
  function addNonTypingUndoLevel (line 14344) | function addNonTypingUndoLevel() {
  function addRootBlocks (line 14556) | function addRootBlocks() {
  function useNativeListForAccessibility (line 14830) | function useNativeListForAccessibility(ed) {
  function isTextBlock (line 15188) | function isTextBlock(name) {
  function getParents (line 15192) | function getParents(node, selector) {
  function isCaretNode (line 15196) | function isCaretNode(node) {
  function defaultFormats (line 15200) | function defaultFormats() {
  function addKeyboardShortcuts (line 15281) | function addKeyboardShortcuts() {
  function get (line 15299) | function get(name) {
  function register (line 15303) | function register(name, format) {
  function apply (line 15366) | function apply(name, vars, node) {
  function remove (line 15749) | function remove(name, vars, node) {
  function toggle (line 15952) | function toggle(name, vars, node) {
  function matchNode (line 15961) | function matchNode(node, name, vars, similar) {
  function match (line 16023) | function match(name, vars, node) {
  function matchAll (line 16055) | function matchAll(names, vars) {
  function canApply (line 16076) | function canApply(name) {
  function formatChanged (line 16100) | function formatChanged(formats, callback, similar) {
  function matchName (line 16176) | function matchName(node, format) {
  function isEq (line 16190) | function isEq(str1, str2) {
  function getStyle (line 16200) | function getStyle(node, name) {
  function replaceVars (line 16214) | function replaceVars(value, vars) {
  function isWhiteSpaceNode (line 16226) | function isWhiteSpaceNode(node) {
  function wrap (line 16230) | function wrap(node, name, attrs) {
  function expandRng (line 16239) | function expandRng(rng, format, remove) {
  function removeFormat (line 16567) | function removeFormat(format, vars, node, compare_node) {
  function removeNode (line 16665) | function removeNode(node, format) {
  function getNonWhiteSpaceSibling (line 16709) | function getNonWhiteSpaceSibling(node, next, inc) {
  function isBookmarkNode (line 16720) | function isBookmarkNode(node) {
  function mergeSiblings (line 16724) | function mergeSiblings(prev, next) {
  function isTextBlock (line 16830) | function isTextBlock(name) {
  function getContainer (line 16834) | function getContainer(rng, start) {
  function performCaretAction (line 16862) | function performCaretAction(type, name, vars) {
  function moveStart (line 17140) | function moveStart(rng) {
  function replaceWithSpan (line 17186) | function replaceWithSpan(node, styles) {
  function convert (line 17195) | function convert(editor, params) {
  function handleEnterKey (line 17246) | function handleEnterKey(evt) {

FILE: static/js/tinymce/utils/form_utils.js
  function getColorPickerHTML (line 13) | function getColorPickerHTML(id, target_form_element) {
  function updateColor (line 26) | function updateColor(img_id, form_element_id) {
  function setBrowserDisabled (line 30) | function setBrowserDisabled(id, state) {
  function getBrowserHTML (line 48) | function getBrowserHTML(id, target_form_element, type, prefix) {
  function openBrowser (line 63) | function openBrowser(img_id, target_form_element, type, option) {
  function selectByValue (line 70) | function selectByValue(form_obj, field_name, value, add_custom, ignore_c...
  function getSelectValue (line 100) | function getSelectValue(form_obj, field_name) {
  function addSelectValue (line 109) | function addSelectValue(form_obj, field_name, name, value) {
  function addClassesToList (line 115) | function addClassesToList(list_id, specific_option) {
  function isVisible (line 141) | function isVisible(element_id) {
  function convertRGBToHex (line 147) | function convertRGBToHex(col) {
  function convertHexToRGB (line 166) | function convertHexToRGB(col) {
  function trimSize (line 180) | function trimSize(size) {
  function getCSSSize (line 184) | function getCSSSize(size) {
  function getStyle (line 200) | function getStyle(elm, attrib, style) {

FILE: static/js/tinymce/utils/mctabs.js
  function MCTabs (line 11) | function MCTabs() {
Condensed preview — 319 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,644K chars).
[
  {
    "path": ".gitignore",
    "chars": 171,
    "preview": "#\n# Project Exclude\n#\n.idea/\ntests/\nnode_modules/\n/doc/todo-jc.txt\n#\n# OS generated files\n#\n.DS_Store\n.DS_Store?\n._*\n.Sp"
  },
  {
    "path": ".npmignore",
    "chars": 42,
    "preview": "archive\nbok\ncodyweb\njsconf\nstef\nstoerhuus\n"
  },
  {
    "path": "Contributing.md",
    "chars": 1909,
    "preview": "Contributing\n============\n\nWe are happy to accept your pull requests. If you do, make sure you clearly explain what and "
  },
  {
    "path": "History.md",
    "chars": 2665,
    "preview": "# History\n## 4.0.1..8 - 08/05/2025 - JC\n* Use url prefix everywhere (also in the back-office !)\n* fix forgotten password"
  },
  {
    "path": "LICENSE.md",
    "chars": 1093,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Johan Coppieters - Howest.\n\nPermission is hereby granted, free of charge, to a"
  },
  {
    "path": "README.md",
    "chars": 4656,
    "preview": "# Cody CMS\n\nA Javascript Content Management System running on Node.js\n\nWe finally took upon the task, we are happy to an"
  },
  {
    "path": "apps/Application.js",
    "chars": 24435,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\n\n\nvar mysql = require('mysql2');\n// JM: assuming Application is always "
  },
  {
    "path": "apps/Dynamic.js",
    "chars": 2438,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar libpath = require(\"path\"),\n  "
  },
  {
    "path": "apps/Static.js",
    "chars": 5359,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar libpath = require(\"path\"),\n  "
  },
  {
    "path": "bin/create_site.js",
    "chars": 7593,
    "preview": "// Tim & Jonas V1.0 -- running from within the cody project directory\n//\n// Johan: v1.1 -- using path, creating a startu"
  },
  {
    "path": "bin/remove_site",
    "chars": 842,
    "preview": "#!/bin/bash\n\n# this is rubbish...  \"Creating tree... dropping the database...\"\n# we should look at the config.json\n#   a"
  },
  {
    "path": "controllers/ContactController.js",
    "chars": 9584,
    "preview": "//\n// Johan Coppieters - first integration into cody code base 29/03/2015\n//\n// alpha 1: uses Model, CRUD operations are"
  },
  {
    "path": "controllers/Controller.js",
    "chars": 13438,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar mysql = require(\"mysql2\");\nva"
  },
  {
    "path": "controllers/DashboardController.js",
    "chars": 599,
    "preview": "//\n// Johan Coppieters - may 2013 - cody\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar cody = require(\"../index.js\");\n"
  },
  {
    "path": "controllers/EmailController.js",
    "chars": 1425,
    "preview": "//\n// Laurens Ramandt - june 2013 - cody\n//\n//\n\n// this class abstracts nodemailer, just in case we would switch from no"
  },
  {
    "path": "controllers/FileController.js",
    "chars": 1198,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nvar mysql = require(\"mysql2\");\nvar cody = require('../index.js');\n\ncons"
  },
  {
    "path": "controllers/FormController.js",
    "chars": 9809,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nvar mysql = require(\"mysql2\");\nvar cody = require('../index.js');\n\ncons"
  },
  {
    "path": "controllers/FormDataController.js",
    "chars": 6086,
    "preview": "//\n// Johan Coppieters - sept 2013 - cody\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar cody = require(\"../index.js\");"
  },
  {
    "path": "controllers/ImageController.js",
    "chars": 1630,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nvar mysql = require(\"mysql2\");\nvar cody = require('../index.js');\n\ncons"
  },
  {
    "path": "controllers/LoginController.js",
    "chars": 4979,
    "preview": "//\n// Johan Coppieters - mar 2013 - cody\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar mysql = require(\"mysql2\");\nvar "
  },
  {
    "path": "controllers/PageController.js",
    "chars": 15302,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nvar mysql = require(\"mysql2\");\nvar cody = require('../index.js');\n\ncons"
  },
  {
    "path": "controllers/StylesController.js",
    "chars": 2915,
    "preview": "\nconsole.log(\"loading \" + module.id);\n\nvar mysql = require(\"mysql2\");\nvar cody = require(\"./../index.js\");\nvar fs = requ"
  },
  {
    "path": "controllers/SystemController.js",
    "chars": 2045,
    "preview": "\nconsole.log(\"loading \" + module.id);\n\nvar mysql = require(\"mysql2\");\nvar cody = require(\"./../index.js\");\nvar fs = requ"
  },
  {
    "path": "controllers/TemplateController.js",
    "chars": 4993,
    "preview": "//\n// Johan Coppieters - may 2013 - cody\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar mysql = require(\"mysql2\");\nvar "
  },
  {
    "path": "controllers/TreeController.js",
    "chars": 14987,
    "preview": "  \n//\n// Johan Coppieters - mar 2013 - cody\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar mysql = require(\"mysql2\");\nv"
  },
  {
    "path": "controllers/UserController.js",
    "chars": 2864,
    "preview": "//\n// Johan Coppieters - mar 2013 - cody\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar mysql = require(\"mysql2\");\nvar "
  },
  {
    "path": "doc/Context.txt",
    "chars": 7375,
    "preview": "//\n// Johan Coppieters - jan 2013 - Cody\n//\n//\n//\n// Context\n//\n// Created by Application in buildContext as results of "
  },
  {
    "path": "doc/empty/controllers/YourController.js",
    "chars": 924,
    "preview": "console.log(\"loading \" + module.id);\nvar cody = require(\"cody\");\n\n\nfunction YourController(context) {\n\n    // init inher"
  },
  {
    "path": "doc/empty/empty.sql",
    "chars": 62174,
    "preview": "SET sql_mode = 'STRICT_TRANS_TABLES';\n\nCREATE FUNCTION PASSWORD2(s VARCHAR(50))\n     RETURNS VARCHAR(50) DETERMINISTIC\n "
  },
  {
    "path": "doc/empty/index.js",
    "chars": 3125,
    "preview": "/**\n * Created by johan on 25/03/15.\n */\n//\n// Johan Coppieters - jan 2013 - Cody CMS\n//\n// empty website for Cody CMS\n/"
  },
  {
    "path": "doc/empty/locales/en.json",
    "chars": 4,
    "preview": "{\t\n}"
  },
  {
    "path": "doc/empty/locales/zh-CN.json",
    "chars": 2628,
    "preview": "{\n\t\"__v\": \"简体中文语言包\",\n\t\"Username\": \"用户名\",\n\t\"Password\": \"密码\",\n\t\"Log on\": \"登陆\",\n\t\"Login\": \"登陆\",\n\t\"Logout\": \"退出\",\n\t\"Dashboar"
  },
  {
    "path": "doc/empty/static/css/front.css",
    "chars": 9210,
    "preview": "\n/* =============================================================================\n   HTML5 Boilerplate CSS: h5bp.com/css"
  },
  {
    "path": "doc/empty/static/js/script.js",
    "chars": 36,
    "preview": "$(document).ready(function() {\n\n\n});"
  },
  {
    "path": "doc/empty/views/content.ejs",
    "chars": 869,
    "preview": "<!doctype html>\n\n<!--[if lt IE 7]> <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\" lang=\"<%=page.language%>\"> <![endif]-->\n<!--"
  },
  {
    "path": "doc/empty/views/footer.ejs",
    "chars": 553,
    "preview": "<footer>\n  <% var first = page.root.getContent('footer.first'); %>\n  <% var second = page.root.getContent('footer.second"
  },
  {
    "path": "doc/empty/views/header.ejs",
    "chars": 1991,
    "preview": "<head>\n  <title><%=page.title%> | <%= (page.parent != page.root) ? (page.parent.title + ' | ') : '' %> <%= page.root.tit"
  },
  {
    "path": "doc/empty/views/index.ejs",
    "chars": 857,
    "preview": "<!doctype html>\n\n<!--[if lt IE 7]> <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\" lang=\"<%=page.language%>\"> <![endif]-->\n<!--"
  },
  {
    "path": "doc/empty/views/intros.ejs",
    "chars": 1057,
    "preview": "<!doctype html>\n\n<!--[if lt IE 7]> <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\" lang=\"<%=page.language%>\"> <![endif]-->\n<!--"
  },
  {
    "path": "doc/empty/views/menu-left.ejs",
    "chars": 455,
    "preview": "<% var theChildren = (page.item.parentId == 1) ? page.children : page.parent.children; %>\n\n<% if (theChildren.length > 0"
  },
  {
    "path": "doc/empty/views/menu-top.ejs",
    "chars": 1586,
    "preview": "<!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href=\"http://browsehappy.com/\">Upgrade to a d"
  },
  {
    "path": "doc/empty/views/page.ejs",
    "chars": 862,
    "preview": "<!doctype html>\n\n<!--[if lt IE 7]> <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\" lang=\"<%=page.language%>\"> <![endif]-->\n<!--"
  },
  {
    "path": "doc/hosting_sqlbased/codymaster.sql",
    "chars": 979,
    "preview": "set names utf8;\n/*!40101 SET NAMES utf8 */;\n\nCREATE DATABASE cody DEFAULT CHARSET=utf8;\nUSE cody;\ngrant all privileges o"
  },
  {
    "path": "doc/hosting_sqlbased/index.js",
    "chars": 1881,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\n\nvar express = require('express');\nvar fs = require('fs');\nvar mysql = "
  },
  {
    "path": "doc/todo.txt",
    "chars": 3141,
    "preview": "\n- model/User.js aanpassen om Model.js te gebruiken.\n  tevens ook nog bug in usercontroller na \"save\", iets met redirect"
  },
  {
    "path": "index.js",
    "chars": 2344,
    "preview": "global.__base = __dirname + '/';\n\nmodule.exports.Application = require(\"./apps/Application.js\");\n\nmodule.exports.Model ="
  },
  {
    "path": "makeWebApp.js",
    "chars": 5806,
    "preview": "console.log(\"loading \" + module.id);\n\nvar cody = require(\"cody\");\nvar express = require(\"express\");\nvar path = require(\""
  },
  {
    "path": "models/Atom.js",
    "chars": 5466,
    "preview": "//\n// Johan Coppieters - jan 2013 - Cody\n//\n//\nconsole.log(\"loading \" + module.id);\nvar fs = require(\"fs\");\n\n\n//!! basis"
  },
  {
    "path": "models/Content.js",
    "chars": 8492,
    "preview": "//\n// Johan Coppieters - may 2013 - cody\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar cody = require(\"../index.js\");\n"
  },
  {
    "path": "models/Context.js",
    "chars": 10369,
    "preview": "//\n// Johan Coppieters - jan 2013 - Cody\n//\n//\nconsole.log(\"loading \" + module.id);\nvar cody = require(\"../index.js\");\n\n"
  },
  {
    "path": "models/Item.js",
    "chars": 7293,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nconsole.log(\"loading \" + module.id);\nvar cody = require('./../index.js'"
  },
  {
    "path": "models/Meta.js",
    "chars": 28447,
    "preview": "//\n// Johan Coppieters - aug 2013 - cody\n//\n//\n\nconsole.log(\"loading \" + module.id);\n\n\n\nfunction Meta(plainObject) {\n  t"
  },
  {
    "path": "models/Model.js",
    "chars": 9235,
    "preview": "\n//\n// Johan Coppieters - apr 2014 - Cody - beta 1\n//\n// beta 2: added \"label\" and \"hide\" in cols.\n//         added loop"
  },
  {
    "path": "models/Page.js",
    "chars": 16540,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar cody = require(\"./../index.js"
  },
  {
    "path": "models/Path.js",
    "chars": 1050,
    "preview": "function Path( path, deflanguage ) {\n  // eliminate leading \"/\"\n  if(path.indexOf(\"/\") === 0){\n    path = path.substring"
  },
  {
    "path": "models/Template.js",
    "chars": 6347,
    "preview": "//\n// Johan Coppieters - jan 2013 - jWorks\n//\n//\nvar cody = require('./../index.js');\n\nconsole.log(\"loading \" + module.i"
  },
  {
    "path": "models/User.js",
    "chars": 8046,
    "preview": "//\n// Johan Coppieters - mar 2013 - cody\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar cody = require(\"./../index.js\")"
  },
  {
    "path": "models/Website.js",
    "chars": 120,
    "preview": "//\n// Johan Coppieters - may 2013 - cody\n//\n//\nconsole.log(\"loading \" + module.id);\n\nvar cody = require(\"../index.js\");\n"
  },
  {
    "path": "package.json",
    "chars": 1093,
    "preview": "{\n  \"author\": {\n    \"name\": \"Howest\"\n  },\n  \"name\": \"cody\",\n  \"description\": \"Cody CMS\",\n  \"version\": \"4.0.15\",\n  \"licen"
  },
  {
    "path": "startWebApp.js",
    "chars": 3215,
    "preview": "console.log(\"loading \" + module.id);\n\nvar cody = require(\"./index.js\");\nvar express = require(\"express\");\nvar vhost = re"
  },
  {
    "path": "startserver.js",
    "chars": 4783,
    "preview": "\"use strict\";\n\n/**\n * Created by johan on 27/04/16.\n *\n * Should be in a directory 1 level up.\n */\n\nvar express = requir"
  },
  {
    "path": "static/css/cody.css",
    "chars": 21473,
    "preview": "/* reset\n------------------------------------------------------------------*/\nhtml, body, div, span, applet, object, ifr"
  },
  {
    "path": "static/css/ui-lightness/jquery-ui-1.10.1.css",
    "chars": 32026,
    "preview": "/*! jQuery UI - v1.10.1 - 2013-03-04\n* http://jqueryui.com\n* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jque"
  },
  {
    "path": "static/js/atom-tree.js",
    "chars": 14069,
    "preview": "\n//Johan Coppieters \n//- mar 2011 - rWorks\n//- mar 2013 - cody\n\n\n\n///////////////////////\n//tree functions    //\n///////"
  },
  {
    "path": "static/js/lib/html5shiv.js",
    "chars": 9498,
    "preview": "/**\n* @preserve HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed\n*/\n;(function(window, document)"
  },
  {
    "path": "static/js/lib/jquery-1.9.1.js",
    "chars": 268381,
    "preview": "/*!\n * jQuery JavaScript Library v1.9.1\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Cop"
  },
  {
    "path": "static/js/lib/jquery-ui-1.10.1.js",
    "chars": 434343,
    "preview": "/*! jQuery UI - v1.10.1 - 2013-03-04\n* http://jqueryui.com\n* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui"
  },
  {
    "path": "static/js/lib/jquery.jstree.js",
    "chars": 179557,
    "preview": "/*\n * jsTree 1.0-rc3\n * http://jstree.com/\n *\n * Copyright (c) 2010 Ivan Bozhanov (vakata.com)\n *\n * Licensed same as jq"
  },
  {
    "path": "static/js/lib/jquery.validate.js",
    "chars": 38014,
    "preview": "/*! jQuery Validation Plugin - v1.11.0 - 2/4/2013\n* https://github.com/jzaefferer/jquery-validation\n* Copyright (c) 2013"
  },
  {
    "path": "static/js/lib/localization/jquery.ui.datepicker-de.js",
    "chars": 877,
    "preview": "/* German initialisation for the jQuery UI date picker plugin. */\n/* Written by Milian Wolff (mail@milianw.de). */\njQuer"
  },
  {
    "path": "static/js/lib/localization/jquery.ui.datepicker-en.js",
    "chars": 874,
    "preview": "/* English/UK initialisation for the jQuery UI date picker plugin. */\n/* Written by Stuart. */\njQuery(function($){\n\t$.da"
  },
  {
    "path": "static/js/lib/localization/jquery.ui.datepicker-es.js",
    "chars": 888,
    "preview": "/* Inicialización en español para la extensión 'UI date picker' para jQuery. */\n/* Traducido por Vester (xvester@gmail.c"
  },
  {
    "path": "static/js/lib/localization/jquery.ui.datepicker-fr.js",
    "chars": 998,
    "preview": "/* French initialisation for the jQuery UI date picker plugin. */\n/* Written by Keith Wood (kbwood{at}iinet.com.au),\n\t\t\t"
  },
  {
    "path": "static/js/lib/localization/jquery.ui.datepicker-nl.js",
    "chars": 918,
    "preview": "/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */\n/* Written by Mathias Bynens <http://mathiasbyn"
  },
  {
    "path": "static/js/lib/localization/messages_de.js",
    "chars": 1099,
    "preview": "/*\n * Translated default messages for the jQuery validation plugin.\n * Locale: DE (German, Deutsch)\n */\n(function ($) {\n"
  },
  {
    "path": "static/js/lib/localization/messages_en.js",
    "chars": 1102,
    "preview": "(function ($) {\n  $.extend($.validator.messages, {\n    required: \"This field is required.\",\n    remote: \"Please fix this"
  },
  {
    "path": "static/js/lib/localization/messages_es.js",
    "chars": 1258,
    "preview": "/*\n * Translated default messages for the jQuery validation plugin.\n * Locale: ES (Spanish; Español)\n */\n(function ($) {"
  },
  {
    "path": "static/js/lib/localization/messages_fr.js",
    "chars": 2791,
    "preview": "/*\n * Translated default messages for the jQuery validation plugin.\n * Locale: FR (French; français)\n */\n(function ($) {"
  },
  {
    "path": "static/js/lib/localization/messages_nl.js",
    "chars": 1187,
    "preview": "/*\n * Translated default messages for the jQuery validation plugin.\n * Locale: NL (Dutch; Nederlands, Vlaams)\n */\n(funct"
  },
  {
    "path": "static/js/lib/themes/apple/style.css",
    "chars": 3987,
    "preview": "/*\n * jsTree apple theme 1.0\n * Supported features: dots/no-dots, icons/no-icons, focused, loading\n * Supported plugins:"
  },
  {
    "path": "static/js/lib/themes/classic/style.css",
    "chars": 4991,
    "preview": "/*\n * jsTree classic theme 1.0\n * Supported features: dots/no-dots, icons/no-icons, focused, loading\n * Supported plugin"
  },
  {
    "path": "static/js/lib/themes/default/style.css",
    "chars": 4724,
    "preview": "/*\n * jsTree default theme 1.0\n * Supported features: dots/no-dots, icons/no-icons, focused, loading\n * Supported plugin"
  },
  {
    "path": "static/js/pages-editor.js",
    "chars": 12022,
    "preview": "//\n// Johan Coppieters \n//   - mar 2011 - rWorks\n//   - mar 2013 - cody\n//\n//\n///////////////////////\n// Editor function"
  },
  {
    "path": "static/js/script.js",
    "chars": 1,
    "preview": "\n"
  },
  {
    "path": "static/js/tinymce/jquery.tinymce.js",
    "chars": 3551,
    "preview": "(function(c){var b,e,a=[],d=window;c.fn.tinymce=function(j){var p=this,g,k,h,m,i,l=\"\",n=\"\";if(!p.length){return p}if(!j)"
  },
  {
    "path": "static/js/tinymce/langs/en.js",
    "chars": 6516,
    "preview": "tinyMCE.addI18n({en:{common:{\"more_colors\":\"More Colors...\",\"invalid_data\":\"Error: Invalid values entered, these are mar"
  },
  {
    "path": "static/js/tinymce/license.txt",
    "chars": 26427,
    "preview": "\t\t  GNU LESSER GENERAL PUBLIC LICENSE\n\t\t       Version 2.1, February 1999\n\n Copyright (C) 1991, 1999 Free Software Found"
  },
  {
    "path": "static/js/tinymce/plugins/advhr/css/advhr.css",
    "chars": 235,
    "preview": "input.radio {border:1px none #000; background:transparent; vertical-align:middle;}\n.panel_wrapper div.current {height:80"
  },
  {
    "path": "static/js/tinymce/plugins/advhr/editor_plugin.js",
    "chars": 847,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.AdvancedHRPlugin\",{init:function(a,b){a.addCommand(\"mceAdvancedHr\",function("
  },
  {
    "path": "static/js/tinymce/plugins/advhr/editor_plugin_src.js",
    "chars": 1386,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/advhr/js/rule.js",
    "chars": 1279,
    "preview": "var AdvHRDialog = {\n\tinit : function(ed) {\n\t\tvar dom = ed.dom, f = document.forms[0], n = ed.selection.getNode(), w;\n\n\t\t"
  },
  {
    "path": "static/js/tinymce/plugins/advhr/langs/en_dlg.js",
    "chars": 117,
    "preview": "tinyMCE.addI18n('en.advhr_dlg',{size:\"Height\",noshade:\"No Shadow\",width:\"Width\",normal:\"Normal\",widthunits:\"Units\"});"
  },
  {
    "path": "static/js/tinymce/plugins/advhr/rule.htm",
    "chars": 2364,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmln"
  },
  {
    "path": "static/js/tinymce/plugins/advimage/css/advimage.css",
    "chars": 659,
    "preview": "#src_list, #over_list, #out_list {width:280px;}\n.mceActionPanel {margin-top:7px;}\n.alignPreview {border:1px solid #000; "
  },
  {
    "path": "static/js/tinymce/plugins/advimage/editor_plugin.js",
    "chars": 791,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.AdvancedImagePlugin\",{init:function(a,b){a.addCommand(\"mceAdvImage\",function"
  },
  {
    "path": "static/js/tinymce/plugins/advimage/editor_plugin_src.js",
    "chars": 1342,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/advimage/image.htm",
    "chars": 11872,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmln"
  },
  {
    "path": "static/js/tinymce/plugins/advimage/js/image.js",
    "chars": 12445,
    "preview": "var ImageDialog = {\n\tpreInit : function() {\n\t\tvar url;\n\n\t\ttinyMCEPopup.requireLangPack();\n\n\t\tif (url = tinyMCEPopup.getP"
  },
  {
    "path": "static/js/tinymce/plugins/advimage/langs/en_dlg.js",
    "chars": 1270,
    "preview": "tinyMCE.addI18n('en.advimage_dlg',{\"image_list\":\"Image List\",\"align_right\":\"Right\",\"align_left\":\"Left\",\"align_textbottom"
  },
  {
    "path": "static/js/tinymce/plugins/advlink/css/advlink.css",
    "chars": 472,
    "preview": ".mceLinkList, .mceAnchorList, #targetlist {width:280px;}\n.mceActionPanel {margin-top:7px;}\n.panel_wrapper div.current {h"
  },
  {
    "path": "static/js/tinymce/plugins/advlink/editor_plugin.js",
    "chars": 973,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.AdvancedLinkPlugin\",{init:function(a,b){this.editor=a;a.addCommand(\"mceAdvLi"
  },
  {
    "path": "static/js/tinymce/plugins/advlink/editor_plugin_src.js",
    "chars": 1573,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/advlink/js/advlink.js",
    "chars": 16798,
    "preview": "/* Functions for the advlink plugin popup */\n\ntinyMCEPopup.requireLangPack();\n\nvar templates = {\n\t\"window.open\" : \"windo"
  },
  {
    "path": "static/js/tinymce/plugins/advlink/langs/en_dlg.js",
    "chars": 1667,
    "preview": "tinyMCE.addI18n('en.advlink_dlg',{\"target_name\":\"Target Name\",classes:\"Classes\",style:\"Style\",id:\"ID\",\"popup_position\":\""
  },
  {
    "path": "static/js/tinymce/plugins/advlink/link.htm",
    "chars": 15785,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmln"
  },
  {
    "path": "static/js/tinymce/plugins/advlist/editor_plugin.js",
    "chars": 2324,
    "preview": "(function(){var a=tinymce.each;tinymce.create(\"tinymce.plugins.AdvListPlugin\",{init:function(b,c){var d=this;d.editor=b;"
  },
  {
    "path": "static/js/tinymce/plugins/advlist/editor_plugin_src.js",
    "chars": 4551,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/autolink/editor_plugin.js",
    "chars": 2355,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.AutolinkPlugin\",{init:function(a,b){var c=this;a.onKeyDown.addToTop(function"
  },
  {
    "path": "static/js/tinymce/plugins/autolink/editor_plugin_src.js",
    "chars": 5309,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2011, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/autoresize/editor_plugin.js",
    "chars": 1506,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.AutoResizePlugin\",{init:function(a,c){var d=this,e=0;if(a.getParam(\"fullscre"
  },
  {
    "path": "static/js/tinymce/plugins/autoresize/editor_plugin_src.js",
    "chars": 4039,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/autosave/editor_plugin.js",
    "chars": 3584,
    "preview": "(function(e){var c=\"autosave\",g=\"restoredraft\",b=true,f,d,a=e.util.Dispatcher;e.create(\"tinymce.plugins.AutoSave\",{init:"
  },
  {
    "path": "static/js/tinymce/plugins/autosave/editor_plugin_src.js",
    "chars": 13333,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/bbcode/editor_plugin.js",
    "chars": 3231,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.BBCodePlugin\",{init:function(a,b){var d=this,c=a.getParam(\"bbcode_dialect\",\""
  },
  {
    "path": "static/js/tinymce/plugins/bbcode/editor_plugin_src.js",
    "chars": 4242,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/contextmenu/editor_plugin.js",
    "chars": 2540,
    "preview": "(function(){var a=tinymce.dom.Event,c=tinymce.each,b=tinymce.DOM;tinymce.create(\"tinymce.plugins.ContextMenu\",{init:func"
  },
  {
    "path": "static/js/tinymce/plugins/contextmenu/editor_plugin_src.js",
    "chars": 5064,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/directionality/editor_plugin.js",
    "chars": 1259,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.Directionality\",{init:function(b,c){var d=this;d.editor=b;function a(e){var "
  },
  {
    "path": "static/js/tinymce/plugins/directionality/editor_plugin_src.js",
    "chars": 2105,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/emotions/editor_plugin.js",
    "chars": 676,
    "preview": "(function(a){a.create(\"tinymce.plugins.EmotionsPlugin\",{init:function(b,c){b.addCommand(\"mceEmotion\",function(){b.window"
  },
  {
    "path": "static/js/tinymce/plugins/emotions/editor_plugin_src.js",
    "chars": 1178,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/emotions/emotions.htm",
    "chars": 5930,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\""
  },
  {
    "path": "static/js/tinymce/plugins/emotions/js/emotions.js",
    "chars": 1077,
    "preview": "tinyMCEPopup.requireLangPack();\n\nvar EmotionsDialog = {\n\taddKeyboardNavigation: function(){\n\t\tvar tableElm, cells, setti"
  },
  {
    "path": "static/js/tinymce/plugins/emotions/langs/en_dlg.js",
    "chars": 420,
    "preview": "tinyMCE.addI18n('en.emotions_dlg',{cry:\"Cry\",cool:\"Cool\",desc:\"Emotions\",title:\"Insert Emotion\",usage:\"Use left and righ"
  },
  {
    "path": "static/js/tinymce/plugins/example/dialog.htm",
    "chars": 886,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmln"
  },
  {
    "path": "static/js/tinymce/plugins/example/editor_plugin.js",
    "chars": 860,
    "preview": "(function(){tinymce.PluginManager.requireLangPack(\"example\");tinymce.create(\"tinymce.plugins.ExamplePlugin\",{init:functi"
  },
  {
    "path": "static/js/tinymce/plugins/example/editor_plugin_src.js",
    "chars": 2906,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/example/js/dialog.js",
    "chars": 590,
    "preview": "tinyMCEPopup.requireLangPack();\n\nvar ExampleDialog = {\n\tinit : function() {\n\t\tvar f = document.forms[0];\n\n\t\t// Get the s"
  },
  {
    "path": "static/js/tinymce/plugins/example/langs/en.js",
    "chars": 76,
    "preview": "tinyMCE.addI18n('en.example',{\n\tdesc : 'This is just a template button'\n});\n"
  },
  {
    "path": "static/js/tinymce/plugins/example/langs/en_dlg.js",
    "chars": 79,
    "preview": "tinyMCE.addI18n('en.example_dlg',{\n\ttitle : 'This is just a example title'\n});\n"
  },
  {
    "path": "static/js/tinymce/plugins/example_dependency/editor_plugin.js",
    "chars": 419,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.ExampleDependencyPlugin\",{init:function(a,b){},getInfo:function(){return{lon"
  },
  {
    "path": "static/js/tinymce/plugins/example_dependency/editor_plugin_src.js",
    "chars": 1835,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/fullpage/css/fullpage.css",
    "chars": 2046,
    "preview": "/* Hide the advanced tab */\n#advanced_tab {\n\tdisplay: none;\n}\n\n#metatitle, #metakeywords, #metadescription, #metaauthor,"
  },
  {
    "path": "static/js/tinymce/plugins/fullpage/editor_plugin.js",
    "chars": 6322,
    "preview": "(function(){var b=tinymce.each,a=tinymce.html.Node;tinymce.create(\"tinymce.plugins.FullPagePlugin\",{init:function(c,d){v"
  },
  {
    "path": "static/js/tinymce/plugins/fullpage/editor_plugin_src.js",
    "chars": 11163,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/fullpage/fullpage.htm",
    "chars": 10495,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmln"
  },
  {
    "path": "static/js/tinymce/plugins/fullpage/js/fullpage.js",
    "chars": 7932,
    "preview": "/**\n * fullpage.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: http://tiny"
  },
  {
    "path": "static/js/tinymce/plugins/fullpage/langs/en_dlg.js",
    "chars": 2297,
    "preview": "tinyMCE.addI18n('en.fullpage_dlg',{title:\"Document Properties\",\"meta_tab\":\"General\",\"appearance_tab\":\"Appearance\",\"advan"
  },
  {
    "path": "static/js/tinymce/plugins/fullscreen/editor_plugin.js",
    "chars": 3618,
    "preview": "(function(){var a=tinymce.DOM;tinymce.create(\"tinymce.plugins.FullScreenPlugin\",{init:function(d,e){var f=this,g={},c,b;"
  },
  {
    "path": "static/js/tinymce/plugins/fullscreen/editor_plugin_src.js",
    "chars": 5484,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/fullscreen/fullscreen.htm",
    "chars": 3262,
    "preview": "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n\t<title></title>\n\t<meta http-equiv=\"X-UA-Compatible\" "
  },
  {
    "path": "static/js/tinymce/plugins/iespell/editor_plugin.js",
    "chars": 909,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.IESpell\",{init:function(a,b){var c=this,d;if(!tinymce.isIE){return}c.editor="
  },
  {
    "path": "static/js/tinymce/plugins/iespell/editor_plugin_src.js",
    "chars": 1431,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/inlinepopups/editor_plugin.js",
    "chars": 11909,
    "preview": "(function(){var d=tinymce.DOM,b=tinymce.dom.Element,a=tinymce.dom.Event,e=tinymce.each,c=tinymce.is;tinymce.create(\"tiny"
  },
  {
    "path": "static/js/tinymce/plugins/inlinepopups/editor_plugin_src.js",
    "chars": 18910,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/inlinepopups/skins/clearlooks2/window.css",
    "chars": 6625,
    "preview": "/* Clearlooks 2 */\n\n/* Reset */\n.clearlooks2, .clearlooks2 div, .clearlooks2 span, .clearlooks2 a {vertical-align:baseli"
  },
  {
    "path": "static/js/tinymce/plugins/inlinepopups/template.htm",
    "chars": 12491,
    "preview": "<!-- <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> -->\n<"
  },
  {
    "path": "static/js/tinymce/plugins/insertdatetime/editor_plugin.js",
    "chars": 1931,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.InsertDateTime\",{init:function(a,b){var c=this;c.editor=a;a.addCommand(\"mceI"
  },
  {
    "path": "static/js/tinymce/plugins/insertdatetime/editor_plugin_src.js",
    "chars": 2778,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/layer/editor_plugin.js",
    "chars": 4052,
    "preview": "(function(){function a(b){do{if(b.className&&b.className.indexOf(\"mceItemLayer\")!=-1){return b}}while(b=b.parentNode)}ti"
  },
  {
    "path": "static/js/tinymce/plugins/layer/editor_plugin_src.js",
    "chars": 6486,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/legacyoutput/editor_plugin.js",
    "chars": 2086,
    "preview": "(function(a){a.onAddEditor.addToTop(function(c,b){b.settings.inline_styles=false});a.create(\"tinymce.plugins.LegacyOutpu"
  },
  {
    "path": "static/js/tinymce/plugins/legacyoutput/editor_plugin_src.js",
    "chars": 4940,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/lists/editor_plugin.js",
    "chars": 14380,
    "preview": "(function(){var e=tinymce.each,r=tinymce.dom.Event,g;function p(t,s){while(t&&(t.nodeType===8||(t.nodeType===3&&/^[ \\t\\n"
  },
  {
    "path": "static/js/tinymce/plugins/lists/editor_plugin_src.js",
    "chars": 31576,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2011, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/media/css/media.css",
    "chars": 1340,
    "preview": "#id, #name, #hspace, #vspace, #class_name, #align { width: 100px }\n#hspace, #vspace { width: 50px }\n#flash_quality, #fla"
  },
  {
    "path": "static/js/tinymce/plugins/media/editor_plugin.js",
    "chars": 12655,
    "preview": "(function(){var b=tinymce.explode(\"id,name,width,height,style,align,class,hspace,vspace,bgcolor,type\"),a=tinymce.makeMap"
  },
  {
    "path": "static/js/tinymce/plugins/media/editor_plugin_src.js",
    "chars": 25521,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/media/js/embed.js",
    "chars": 1865,
    "preview": "/**\n * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose.\n "
  },
  {
    "path": "static/js/tinymce/plugins/media/js/media.js",
    "chars": 15960,
    "preview": "(function() {\n\tvar url;\n\n\tif (url = tinyMCEPopup.getParam(\"media_external_list_url\"))\n\t\tdocument.write('<script language"
  },
  {
    "path": "static/js/tinymce/plugins/media/langs/en_dlg.js",
    "chars": 2814,
    "preview": "tinyMCE.addI18n('en.media_dlg',{list:\"List\",file:\"File/URL\",advanced:\"Advanced\",general:\"General\",title:\"Insert/Edit Emb"
  },
  {
    "path": "static/js/tinymce/plugins/media/media.htm",
    "chars": 37930,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmln"
  },
  {
    "path": "static/js/tinymce/plugins/nonbreaking/editor_plugin.js",
    "chars": 944,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.Nonbreaking\",{init:function(a,b){var c=this;c.editor=a;a.addCommand(\"mceNonB"
  },
  {
    "path": "static/js/tinymce/plugins/nonbreaking/editor_plugin_src.js",
    "chars": 1468,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/noneditable/editor_plugin.js",
    "chars": 5431,
    "preview": "(function(){var c=tinymce.dom.TreeWalker;var a=\"contenteditable\",d=\"data-mce-\"+a;var e=tinymce.VK;function b(n){var j=n."
  },
  {
    "path": "static/js/tinymce/plugins/noneditable/editor_plugin_src.js",
    "chars": 16618,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/pagebreak/editor_plugin.js",
    "chars": 1402,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.PageBreakPlugin\",{init:function(b,d){var f='<img src=\"'+b.theme.url+'/img/tr"
  },
  {
    "path": "static/js/tinymce/plugins/pagebreak/editor_plugin_src.js",
    "chars": 2088,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/paste/editor_plugin.js",
    "chars": 13616,
    "preview": "(function(){var c=tinymce.each,a={paste_auto_cleanup_on_paste:true,paste_enable_default_filters:true,paste_block_drop:fa"
  },
  {
    "path": "static/js/tinymce/plugins/paste/editor_plugin_src.js",
    "chars": 30591,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/paste/js/pastetext.js",
    "chars": 848,
    "preview": "tinyMCEPopup.requireLangPack();\n\nvar PasteTextDialog = {\n\tinit : function() {\n\t\tthis.resize();\n\t},\n\n\tinsert : function()"
  },
  {
    "path": "static/js/tinymce/plugins/paste/js/pasteword.js",
    "chars": 1596,
    "preview": "tinyMCEPopup.requireLangPack();\n\nvar PasteWordDialog = {\n\tinit : function() {\n\t\tvar ed = tinyMCEPopup.editor, el = docum"
  },
  {
    "path": "static/js/tinymce/plugins/paste/langs/en_dlg.js",
    "chars": 226,
    "preview": "tinyMCE.addI18n('en.paste_dlg',{\"word_title\":\"Use Ctrl+V on your keyboard to paste the text into the window.\",\"text_line"
  },
  {
    "path": "static/js/tinymce/plugins/paste/pastetext.htm",
    "chars": 1183,
    "preview": "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n\t<title>{#paste.paste_text_desc}</title>\n\t<script type=\"text/javascri"
  },
  {
    "path": "static/js/tinymce/plugins/paste/pasteword.htm",
    "chars": 762,
    "preview": "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n\t<title>{#paste.paste_word_desc}</title>\n\t<script type=\"text/javascri"
  },
  {
    "path": "static/js/tinymce/plugins/preview/editor_plugin.js",
    "chars": 1051,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.Preview\",{init:function(a,b){var d=this,c=tinymce.explode(a.settings.content"
  },
  {
    "path": "static/js/tinymce/plugins/preview/editor_plugin_src.js",
    "chars": 1589,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/preview/example.html",
    "chars": 703,
    "preview": "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<script language=\"javascript\" src=\"../../tiny_mce_popup.js\"></script>"
  },
  {
    "path": "static/js/tinymce/plugins/preview/jscripts/embed.js",
    "chars": 1865,
    "preview": "/**\n * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose.\n "
  },
  {
    "path": "static/js/tinymce/plugins/preview/preview.html",
    "chars": 613,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\""
  },
  {
    "path": "static/js/tinymce/plugins/print/editor_plugin.js",
    "chars": 492,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.Print\",{init:function(a,b){a.addCommand(\"mcePrint\",function(){a.getWin().pri"
  },
  {
    "path": "static/js/tinymce/plugins/print/editor_plugin_src.js",
    "chars": 847,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/save/editor_plugin.js",
    "chars": 1569,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.Save\",{init:function(a,b){var c=this;c.editor=a;a.addCommand(\"mceSave\",c._sa"
  },
  {
    "path": "static/js/tinymce/plugins/save/editor_plugin_src.js",
    "chars": 2429,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/searchreplace/css/searchreplace.css",
    "chars": 170,
    "preview": ".panel_wrapper {height:85px;}\n.panel_wrapper div.current {height:85px;}\n\n/* IE */\n* html .panel_wrapper {height:100px;}\n"
  },
  {
    "path": "static/js/tinymce/plugins/searchreplace/editor_plugin.js",
    "chars": 1046,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.SearchReplacePlugin\",{init:function(a,c){function b(d){window.focus();a.wind"
  },
  {
    "path": "static/js/tinymce/plugins/searchreplace/editor_plugin_src.js",
    "chars": 1735,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/searchreplace/js/searchreplace.js",
    "chars": 3546,
    "preview": "tinyMCEPopup.requireLangPack();\n\nvar SearchReplaceDialog = {\n\tinit : function(ed) {\n\t\tvar t = this, f = document.forms[0"
  },
  {
    "path": "static/js/tinymce/plugins/searchreplace/langs/en_dlg.js",
    "chars": 445,
    "preview": "tinyMCE.addI18n('en.searchreplace_dlg',{findwhat:\"Find What\",replacewith:\"Replace with\",direction:\"Direction\",up:\"Up\",do"
  },
  {
    "path": "static/js/tinymce/plugins/searchreplace/searchreplace.htm",
    "chars": 5234,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmln"
  },
  {
    "path": "static/js/tinymce/plugins/spellchecker/css/content.css",
    "chars": 97,
    "preview": ".mceItemHiddenSpellWord {background:url(../img/wline.gif) repeat-x bottom left; cursor:default;}\n"
  },
  {
    "path": "static/js/tinymce/plugins/spellchecker/editor_plugin.js",
    "chars": 6860,
    "preview": "(function(){var a=tinymce.util.JSONRequest,c=tinymce.each,b=tinymce.DOM;tinymce.create(\"tinymce.plugins.SpellcheckerPlug"
  },
  {
    "path": "static/js/tinymce/plugins/spellchecker/editor_plugin_src.js",
    "chars": 11586,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/style/css/props.css",
    "chars": 892,
    "preview": "#text_font {width:250px;}\n#text_size {width:70px;}\n.mceAddSelectValue {background:#DDD;}\nselect, #block_text_indent, #bo"
  },
  {
    "path": "static/js/tinymce/plugins/style/editor_plugin.js",
    "chars": 1117,
    "preview": "(function(){tinymce.create(\"tinymce.plugins.StylePlugin\",{init:function(a,b){a.addCommand(\"mceStyleProps\",function(){var"
  },
  {
    "path": "static/js/tinymce/plugins/style/editor_plugin_src.js",
    "chars": 1856,
    "preview": "/**\n * editor_plugin_src.js\n *\n * Copyright 2009, Moxiecode Systems AB\n * Released under LGPL License.\n *\n * License: ht"
  },
  {
    "path": "static/js/tinymce/plugins/style/js/props.js",
    "chars": 31646,
    "preview": "tinyMCEPopup.requireLangPack();\n\nvar defaultFonts = \"\" + \n\t\"Arial, Helvetica, sans-serif=Arial, Helvetica, sans-serif;\" "
  },
  {
    "path": "static/js/tinymce/plugins/style/langs/en_dlg.js",
    "chars": 1626,
    "preview": "tinyMCE.addI18n('en.style_dlg',{\"text_lineheight\":\"Line Height\",\"text_variant\":\"Variant\",\"text_style\":\"Style\",\"text_weig"
  },
  {
    "path": "static/js/tinymce/plugins/style/props.htm",
    "chars": 37649,
    "preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmln"
  },
  {
    "path": "static/js/tinymce/plugins/style/readme.txt",
    "chars": 1011,
    "preview": "Edit CSS Style plug-in notes\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nUnlike WYSIWYG editor functionality that operates only on the "
  }
]

// ... and 119 more files (download for full content)

About this extraction

This page contains the full source code of the jcoppieters/cody GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 319 files (3.1 MB), approximately 832.7k tokens, and a symbol index with 915 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!