You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by ge...@apache.org on 2019/10/15 13:34:29 UTC

[netbeans-tools] branch master updated: NetBeans Pluginportal v3

This is an automated email from the ASF dual-hosted git repository.

geertjan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans-tools.git


The following commit(s) were added to refs/heads/master by this push:
     new 0a6c660  NetBeans Pluginportal v3
     new 764dd8f  Merge pull request #10 from jpirek/master
0a6c660 is described below

commit 0a6c660a630d6b8b1b959c42685e27f5ae73d76b
Author: Jan Pirek <ja...@oracle.com>
AuthorDate: Tue Oct 15 15:28:36 2019 +0200

    NetBeans Pluginportal v3
---
 pp3/.gitignore                                     |   14 +
 pp3/README.txt                                     |   12 +
 pp3/composer.json                                  |   22 +
 pp3/config/application.config.php                  |   73 +
 pp3/config/autoload/.gitignore                     |    2 +
 pp3/config/autoload/README.md                      |    8 +
 pp3/config/autoload/global.php                     |   16 +
 pp3/config/autoload/local.php.dist                 |   14 +
 pp3/config/autoupdate-catalog-2_6.dtd              |   67 +
 pp3/config/erd.png                                 |  Bin 0 -> 76339 bytes
 pp3/config/pp3.sql                                 |  165 +
 pp3/init_autoloader.php                            |   52 +
 pp3/module/Application/Module.php                  |   54 +
 pp3/module/Application/config/.gitignore           |    1 +
 .../Application/config/module.config.php.dist      |  226 +
 pp3/module/Application/language/cs_CZ.mo           |  Bin 0 -> 5001 bytes
 pp3/module/Application/language/cs_CZ.po           |  153 +
 pp3/module/Application/language/en_US.mo           |  Bin 0 -> 545 bytes
 pp3/module/Application/language/en_US.po           |  153 +
 .../src/Application/Controller/AdminController.php |  397 ++
 .../src/Application/Controller/BaseController.php  |   44 +
 .../src/Application/Controller/IndexController.php |   79 +
 .../src/Application/Controller/LoginController.php |   63 +
 .../Application/Controller/PluginController.php    |  351 +
 .../Controller/PluginVersionController.php         |  126 +
 .../Controller/VerificationController.php          |  238 +
 .../src/Application/Entity/Base/Category.php       |   50 +
 .../src/Application/Entity/Base/NbVersion.php      |   61 +
 .../Entity/Base/NbVersionPluginVersion.php         |   93 +
 .../src/Application/Entity/Base/Plugin.php         |  240 +
 .../src/Application/Entity/Base/PluginVersion.php  |   98 +
 .../src/Application/Entity/Base/Verification.php   |   85 +
 .../Entity/Base/VerificationRequest.php            |  121 +
 .../src/Application/Entity/Base/Verifier.php       |   50 +
 .../src/Application/Entity/Category.php            |   13 +
 .../src/Application/Entity/NbVersion.php           |   16 +
 .../Application/Entity/NbVersionPluginVersion.php  |   13 +
 .../Application/src/Application/Entity/Plugin.php  |  164 +
 .../src/Application/Entity/PluginVersion.php       |   44 +
 .../src/Application/Entity/Verification.php        |   70 +
 .../src/Application/Entity/VerificationRequest.php |   64 +
 .../src/Application/Entity/Verifier.php            |   13 +
 .../Application/Factory/AdminControllerFactory.php |   52 +
 .../Application/Factory/IndexControllerFactory.php |   33 +
 .../Application/Factory/LoginControllerFactory.php |   22 +
 .../Factory/PluginControllerFactory.php            |   34 +
 .../Factory/PluginVersionControllerFactory.php     |   34 +
 .../Factory/VerificationControllerFactory.php      |   37 +
 .../Application/src/Application/Pp/Catalog.php     |   94 +
 .../src/Application/Pp/MavenDataLoader.php         |   48 +
 .../Application/Repository/CategoryRepository.php  |   22 +
 .../Repository/DoctrineEntityRepository.php        |  158 +
 .../NbVersionPluginVersionRepository.php           |   21 +
 .../Application/Repository/NbVersionRepository.php |   38 +
 .../Application/Repository/PluginRepository.php    |  130 +
 .../Repository/PluginVersionRepository.php         |   49 +
 .../Repository/VerificationRepository.php          |   14 +
 .../Repository/VerificationRequestRepository.php   |   59 +
 .../Application/Repository/VerifierRepository.php  |   23 +
 .../Application/view/application/admin/_nav.phtml  |   10 +
 .../view/application/admin/_plugin-listrow.phtml   |  101 +
 .../view/application/admin/_pluginRowItem.phtml    |   26 +
 .../view/application/admin/approve.phtml           |   44 +
 .../view/application/admin/catalog.phtml           |   27 +
 .../view/application/admin/categories.phtml        |   29 +
 .../Application/view/application/admin/edit.phtml  |   12 +
 .../Application/view/application/admin/index.phtml |   45 +
 .../view/application/admin/nb-versions.phtml       |   29 +
 .../view/application/admin/verifiers.phtml         |   29 +
 .../view/application/index/catalogue.phtml         |   83 +
 .../Application/view/application/index/index.phtml |  145 +
 .../Application/view/application/login/index.phtml |   16 +
 .../plugin-version/_pluginVersion-form.phtml       |   18 +
 .../view/application/plugin-version/edit.phtml     |   16 +
 .../view/application/plugin/_plugin-form.phtml     |   53 +
 .../view/application/plugin/_plugin-listrow.phtml  |   76 +
 .../view/application/plugin/confirm.phtml          |   12 +
 .../Application/view/application/plugin/edit.phtml |   12 +
 .../view/application/plugin/index.phtml            |   20 +
 .../Application/view/application/plugin/list.phtml |   23 +
 .../view/application/verification/list.phtml       |  107 +
 pp3/module/Application/view/error/404.phtml        |  113 +
 pp3/module/Application/view/error/index.phtml      |   68 +
 pp3/module/Application/view/layout/flash.phtml     |   13 +
 pp3/module/Application/view/layout/layout.phtml    |  111 +
 .../view/partials/_categories-select.phtml         |   11 +
 .../view/partials/_nbVersion-select.phtml          |   36 +
 .../Application/view/partials/_paginator.phtml     |   46 +
 pp3/public/.htaccess                               |   16 +
 pp3/public/css/bootstrap-theme.css                 |  397 ++
 pp3/public/css/bootstrap-theme.min.css             |    7 +
 pp3/public/css/bootstrap.css                       | 7118 ++++++++++++++++++++
 pp3/public/css/bootstrap.min.css                   |    7 +
 pp3/public/css/font-awesome.min.css                |    4 +
 pp3/public/fonts/FontAwesome.otf                   |  Bin 0 -> 124988 bytes
 pp3/public/fonts/fontawesome-webfont.eot           |  Bin 0 -> 76518 bytes
 pp3/public/fonts/fontawesome-webfont.svg           |  685 ++
 pp3/public/fonts/fontawesome-webfont.ttf           |  Bin 0 -> 152796 bytes
 pp3/public/fonts/fontawesome-webfont.woff          |  Bin 0 -> 90412 bytes
 pp3/public/fonts/fontawesome-webfont.woff2         |  Bin 0 -> 71896 bytes
 pp3/public/fonts/glyphicons-halflings-regular.eot  |  Bin 0 -> 20290 bytes
 pp3/public/fonts/glyphicons-halflings-regular.svg  |  229 +
 pp3/public/fonts/glyphicons-halflings-regular.ttf  |  Bin 0 -> 41236 bytes
 pp3/public/fonts/glyphicons-halflings-regular.woff |  Bin 0 -> 23292 bytes
 pp3/public/img/apache-netbeans.svg                 |   36 +
 pp3/public/img/favicon.ico                         |  Bin 0 -> 1406 bytes
 pp3/public/img/zf2-logo.png                        |  Bin 0 -> 738 bytes
 pp3/public/index.php                               |   21 +
 pp3/public/js/bootstrap.js                         | 2006 ++++++
 pp3/public/js/bootstrap.min.js                     |    7 +
 .../js/datepicker/css/bootstrap-datepicker.css     |  474 ++
 .../js/datepicker/css/bootstrap-datepicker.css.map |    1 +
 .../js/datepicker/css/bootstrap-datepicker.min.css |    9 +
 .../css/bootstrap-datepicker.min.css.map           |    1 +
 .../css/bootstrap-datepicker.standalone.css        |  507 ++
 .../css/bootstrap-datepicker.standalone.css.map    |    1 +
 .../css/bootstrap-datepicker.standalone.min.css    |    9 +
 .../bootstrap-datepicker.standalone.min.css.map    |    1 +
 .../js/datepicker/css/bootstrap-datepicker3.css    |  681 ++
 .../datepicker/css/bootstrap-datepicker3.css.map   |    1 +
 .../datepicker/css/bootstrap-datepicker3.min.css   |    9 +
 .../css/bootstrap-datepicker3.min.css.map          |    1 +
 .../css/bootstrap-datepicker3.standalone.css       |  710 ++
 .../css/bootstrap-datepicker3.standalone.css.map   |    1 +
 .../css/bootstrap-datepicker3.standalone.min.css   |    9 +
 .../bootstrap-datepicker3.standalone.min.css.map   |    1 +
 .../js/datepicker/js/bootstrap-datepicker.js       | 2089 ++++++
 .../js/datepicker/js/bootstrap-datepicker.min.js   |    9 +
 .../locales/bootstrap-datepicker.en-GB.min.js      |    1 +
 pp3/public/js/html5shiv.js                         |  322 +
 pp3/public/js/html5shiv.min.js                     |    4 +
 pp3/public/js/jquery-1.11.1.min.map                |    1 +
 pp3/public/js/jquery.ba-throttle-debounce.min.js   |    9 +
 pp3/public/js/jquery.min.js                        |    4 +
 pp3/public/js/respond.min.js                       |    6 +
 pp3/public/js/script.js                            |   71 +
 pp3/public/js/tinymce/jquery.tinymce.min.js        |    1 +
 pp3/public/js/tinymce/langs/readme.md              |    3 +
 pp3/public/js/tinymce/license.txt                  |  504 ++
 .../js/tinymce/plugins/advlist/plugin.min.js       |    1 +
 pp3/public/js/tinymce/plugins/anchor/plugin.min.js |    1 +
 .../js/tinymce/plugins/autolink/plugin.min.js      |    1 +
 .../js/tinymce/plugins/autoresize/plugin.min.js    |    1 +
 .../js/tinymce/plugins/autosave/plugin.min.js      |    1 +
 pp3/public/js/tinymce/plugins/bbcode/plugin.min.js |    1 +
 .../js/tinymce/plugins/charmap/plugin.min.js       |    1 +
 pp3/public/js/tinymce/plugins/code/plugin.min.js   |    1 +
 .../js/tinymce/plugins/codesample/css/prism.css    |  138 +
 .../js/tinymce/plugins/codesample/plugin.min.js    |    1 +
 .../js/tinymce/plugins/colorpicker/plugin.min.js   |    1 +
 .../js/tinymce/plugins/contextmenu/plugin.min.js   |    1 +
 .../tinymce/plugins/directionality/plugin.min.js   |    1 +
 .../tinymce/plugins/emoticons/img/smiley-cool.gif  |  Bin 0 -> 354 bytes
 .../tinymce/plugins/emoticons/img/smiley-cry.gif   |  Bin 0 -> 329 bytes
 .../plugins/emoticons/img/smiley-embarassed.gif    |  Bin 0 -> 331 bytes
 .../plugins/emoticons/img/smiley-foot-in-mouth.gif |  Bin 0 -> 342 bytes
 .../tinymce/plugins/emoticons/img/smiley-frown.gif |  Bin 0 -> 340 bytes
 .../plugins/emoticons/img/smiley-innocent.gif      |  Bin 0 -> 336 bytes
 .../tinymce/plugins/emoticons/img/smiley-kiss.gif  |  Bin 0 -> 338 bytes
 .../plugins/emoticons/img/smiley-laughing.gif      |  Bin 0 -> 343 bytes
 .../plugins/emoticons/img/smiley-money-mouth.gif   |  Bin 0 -> 321 bytes
 .../plugins/emoticons/img/smiley-sealed.gif        |  Bin 0 -> 323 bytes
 .../tinymce/plugins/emoticons/img/smiley-smile.gif |  Bin 0 -> 344 bytes
 .../plugins/emoticons/img/smiley-surprised.gif     |  Bin 0 -> 338 bytes
 .../plugins/emoticons/img/smiley-tongue-out.gif    |  Bin 0 -> 328 bytes
 .../plugins/emoticons/img/smiley-undecided.gif     |  Bin 0 -> 337 bytes
 .../tinymce/plugins/emoticons/img/smiley-wink.gif  |  Bin 0 -> 350 bytes
 .../tinymce/plugins/emoticons/img/smiley-yell.gif  |  Bin 0 -> 336 bytes
 .../js/tinymce/plugins/emoticons/plugin.min.js     |    1 +
 pp3/public/js/tinymce/plugins/example/dialog.html  |    8 +
 .../js/tinymce/plugins/example/plugin.min.js       |    1 +
 .../plugins/example_dependency/plugin.min.js       |    1 +
 .../js/tinymce/plugins/fullpage/plugin.min.js      |    1 +
 .../js/tinymce/plugins/fullscreen/plugin.min.js    |    1 +
 pp3/public/js/tinymce/plugins/hr/plugin.min.js     |    1 +
 pp3/public/js/tinymce/plugins/image/plugin.min.js  |    1 +
 .../js/tinymce/plugins/imagetools/plugin.min.js    |    1 +
 .../js/tinymce/plugins/importcss/plugin.min.js     |    1 +
 .../tinymce/plugins/insertdatetime/plugin.min.js   |    1 +
 pp3/public/js/tinymce/plugins/layer/plugin.min.js  |    1 +
 .../js/tinymce/plugins/legacyoutput/plugin.min.js  |    1 +
 pp3/public/js/tinymce/plugins/link/plugin.min.js   |    1 +
 pp3/public/js/tinymce/plugins/lists/plugin.min.js  |    1 +
 .../js/tinymce/plugins/media/moxieplayer.swf       |  Bin 0 -> 20017 bytes
 pp3/public/js/tinymce/plugins/media/plugin.min.js  |    1 +
 .../js/tinymce/plugins/nonbreaking/plugin.min.js   |    1 +
 .../js/tinymce/plugins/noneditable/plugin.min.js   |    1 +
 .../js/tinymce/plugins/pagebreak/plugin.min.js     |    1 +
 pp3/public/js/tinymce/plugins/paste/plugin.min.js  |    1 +
 .../js/tinymce/plugins/preview/plugin.min.js       |    1 +
 pp3/public/js/tinymce/plugins/print/plugin.min.js  |    1 +
 pp3/public/js/tinymce/plugins/save/plugin.min.js   |    1 +
 .../js/tinymce/plugins/searchreplace/plugin.min.js |    1 +
 .../js/tinymce/plugins/spellchecker/plugin.min.js  |    1 +
 .../js/tinymce/plugins/tabfocus/plugin.min.js      |    1 +
 pp3/public/js/tinymce/plugins/table/plugin.min.js  |    2 +
 .../js/tinymce/plugins/template/plugin.min.js      |    1 +
 .../js/tinymce/plugins/textcolor/plugin.min.js     |    1 +
 .../js/tinymce/plugins/textpattern/plugin.min.js   |    1 +
 .../plugins/visualblocks/css/visualblocks.css      |  135 +
 .../js/tinymce/plugins/visualblocks/plugin.min.js  |    1 +
 .../js/tinymce/plugins/visualchars/plugin.min.js   |    1 +
 .../js/tinymce/plugins/wordcount/plugin.min.js     |    1 +
 .../tinymce/skins/lightgray/content.inline.min.css |    1 +
 .../js/tinymce/skins/lightgray/content.min.css     |    1 +
 .../skins/lightgray/fonts/tinymce-small.eot        |  Bin 0 -> 9492 bytes
 .../skins/lightgray/fonts/tinymce-small.svg        |   63 +
 .../skins/lightgray/fonts/tinymce-small.ttf        |  Bin 0 -> 9304 bytes
 .../skins/lightgray/fonts/tinymce-small.woff       |  Bin 0 -> 9380 bytes
 .../js/tinymce/skins/lightgray/fonts/tinymce.eot   |  Bin 0 -> 17292 bytes
 .../js/tinymce/skins/lightgray/fonts/tinymce.svg   |  129 +
 .../js/tinymce/skins/lightgray/fonts/tinymce.ttf   |  Bin 0 -> 17128 bytes
 .../js/tinymce/skins/lightgray/fonts/tinymce.woff  |  Bin 0 -> 17204 bytes
 .../js/tinymce/skins/lightgray/img/anchor.gif      |  Bin 0 -> 53 bytes
 .../js/tinymce/skins/lightgray/img/loader.gif      |  Bin 0 -> 2608 bytes
 .../js/tinymce/skins/lightgray/img/object.gif      |  Bin 0 -> 152 bytes
 .../js/tinymce/skins/lightgray/img/trans.gif       |  Bin 0 -> 43 bytes
 .../js/tinymce/skins/lightgray/skin.ie7.min.css    |    1 +
 pp3/public/js/tinymce/skins/lightgray/skin.min.css |    1 +
 .../js/tinymce/themes/inlite/config/bolt/atomic.js |    5 +
 .../themes/inlite/config/bolt/bootstrap-atomic.js  | 1491 ++++
 .../themes/inlite/config/bolt/bootstrap-browser.js | 1491 ++++
 .../themes/inlite/config/bolt/bootstrap-demo.js    | 1491 ++++
 .../themes/inlite/config/bolt/bootstrap-prod.js    | 1491 ++++
 .../tinymce/themes/inlite/config/bolt/browser.js   |   10 +
 .../js/tinymce/themes/inlite/config/bolt/demo.js   |    8 +
 .../js/tinymce/themes/inlite/config/bolt/prod.js   |    5 +
 .../js/tinymce/themes/inlite/config/dent/depend.js |   21 +
 .../themes/inlite/scratch/compile/bootstrap.js     | 1526 +++++
 .../tinymce/themes/inlite/scratch/compile/theme.js | 1594 +++++
 .../tinymce/themes/inlite/scratch/inline/theme.js  | 1679 +++++
 .../themes/inlite/scratch/inline/theme.raw.js      | 1679 +++++
 .../js/tinymce/themes/inlite/src/demo/css/demo.css |   25 +
 .../tinymce/themes/inlite/src/demo/html/demo.html  |   69 +
 .../inlite/src/demo/js/tinymce/inlite/Demo.js      |   28 +
 .../inlite/src/main/js/tinymce/inlite/Theme.js     |  150 +
 .../inlite/src/main/js/tinymce/inlite/alien/Arr.js |   22 +
 .../src/main/js/tinymce/inlite/alien/Bookmark.js   |  130 +
 .../src/main/js/tinymce/inlite/alien/Unlink.js     |   84 +
 .../src/main/js/tinymce/inlite/alien/Uuid.js       |   34 +
 .../src/main/js/tinymce/inlite/core/Actions.js     |  106 +
 .../src/main/js/tinymce/inlite/core/Convert.js     |   37 +
 .../main/js/tinymce/inlite/core/ElementMatcher.js  |   47 +
 .../src/main/js/tinymce/inlite/core/Layout.js      |   95 +
 .../src/main/js/tinymce/inlite/core/Matcher.js     |   39 +
 .../src/main/js/tinymce/inlite/core/Measure.js     |   61 +
 .../src/main/js/tinymce/inlite/core/PredicateId.js |   32 +
 .../js/tinymce/inlite/core/SelectionMatcher.js     |   55 +
 .../src/main/js/tinymce/inlite/core/SkinLoader.js  |   45 +
 .../src/main/js/tinymce/inlite/core/UrlType.js     |   27 +
 .../src/main/js/tinymce/inlite/file/Conversions.js |   31 +
 .../src/main/js/tinymce/inlite/file/Picker.js      |   40 +
 .../src/main/js/tinymce/inlite/ui/Buttons.js       |   80 +
 .../inlite/src/main/js/tinymce/inlite/ui/Forms.js  |  102 +
 .../inlite/src/main/js/tinymce/inlite/ui/Panel.js  |  218 +
 .../src/main/js/tinymce/inlite/ui/Toolbar.js       |  126 +
 .../js/tinymce/themes/inlite/src/test/.eslintrc    |   14 +
 .../inlite/src/test/js/atomic/alien/ArrTest.js     |    9 +
 .../inlite/src/test/js/atomic/alien/UuidTest.js    |   10 +
 .../inlite/src/test/js/atomic/core/ConvertTest.js  |   12 +
 .../inlite/src/test/js/atomic/core/MatcherTest.js  |   51 +
 .../inlite/src/test/js/atomic/core/UrlTypeTest.js  |   33 +
 .../themes/inlite/src/test/js/browser/ThemeTest.js |  202 +
 .../src/test/js/browser/alien/BookmarkTest.js      |   65 +
 .../inlite/src/test/js/browser/alien/UnlinkTest.js |   38 +
 .../inlite/src/test/js/browser/core/ActionsTest.js |  177 +
 .../src/test/js/browser/core/ElementMatcher.js     |   69 +
 .../inlite/src/test/js/browser/core/LayoutTest.js  |  118 +
 .../inlite/src/test/js/browser/core/MeasureTest.js |   62 +
 .../src/test/js/browser/core/PredicateIdTest.js    |   26 +
 .../test/js/browser/core/SelectionMatcherTest.js   |   76 +
 .../src/test/js/browser/file/ConversionsTest.js    |   41 +
 .../src/test/js/browser/file/SelectionMatcher.js   |   55 +
 pp3/public/js/tinymce/themes/inlite/theme.min.js   |    1 +
 pp3/public/js/tinymce/themes/modern/theme.min.js   |    1 +
 pp3/public/js/tinymce/tinymce.min.js               |   13 +
 pp3/public/js/validator.min.js                     |    9 +
 pp3/public/scss/style.css                          |   69 +
 pp3/public/scss/style.css.map                      |    9 +
 pp3/public/scss/style.scss                         |   57 +
 280 files changed, 37610 insertions(+)

diff --git a/pp3/.gitignore b/pp3/.gitignore
new file mode 100755
index 0000000..8e1aced
--- /dev/null
+++ b/pp3/.gitignore
@@ -0,0 +1,14 @@
+._*
+.vagrant
+.~lock.*
+.buildpath
+.DS_Store
+.idea
+.project
+.settings
+composer.lock
+vendor/*
+composer.phar
+public/data/*
+data/*
+nbproject
\ No newline at end of file
diff --git a/pp3/README.txt b/pp3/README.txt
new file mode 100644
index 0000000..62eff5a
--- /dev/null
+++ b/pp3/README.txt
@@ -0,0 +1,12 @@
+Local Setup Instructions:
+
+0) required software: php >=5.6 cli, web server with php >=5.6 (apache, nginx...), mysql >=5.7, composer 
+1) clone project
+2) in root folder run $ composer install
+3) copy over config .dist files and set proper values there 
+	config/autoload/
+	module/Application/config/
+4) setup local database with config/pp3.sql script
+5) to become admin user add your google email into module/Application/config/module.config.php: pp3->admin property 
+6) open pp3/public/ folder in teh browser to see the application
+7) set write access to data/ and public/data folders so app can store files
diff --git a/pp3/composer.json b/pp3/composer.json
new file mode 100755
index 0000000..fc68677
--- /dev/null
+++ b/pp3/composer.json
@@ -0,0 +1,22 @@
+{
+    "name": "zendframework/skeleton-application",
+    "description": "Skeleton Application for ZF2",
+    "license": "BSD-3-Clause",
+    "keywords": [
+        "framework",
+        "zf2"
+    ],
+    "config": {
+        "discard-changes": true
+    },  
+    "homepage": "http://framework.zend.com/",
+    "require": {
+        "php": ">=5.5",
+        "zendframework/zendframework": "~2.5",
+        "zendframework/zend-developer-tools": "dev-master",
+        "doctrine/doctrine-orm-module": "^0.9.1",
+        "ezyang/htmlpurifier": "^4.10",
+        "zendframework/zendoauth": "2.0.*",
+        "knplabs/knp-paginator-bundle": "^3.0"
+    }
+}
diff --git a/pp3/config/application.config.php b/pp3/config/application.config.php
new file mode 100755
index 0000000..1bb26f6
--- /dev/null
+++ b/pp3/config/application.config.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * If you need an environment-specific system or application configuration,
+ * there is an example in the documentation
+ * @see http://framework.zend.com/manual/current/en/tutorials/config.advanced.html#environment-specific-system-configuration
+ * @see http://framework.zend.com/manual/current/en/tutorials/config.advanced.html#environment-specific-application-configuration
+ */
+return array(
+    // This should be an array of module namespaces used in the application.
+    'modules' => array(
+        // 'ZendDeveloperTools',
+        'DoctrineModule',
+        'DoctrineORMModule',
+        'Application',
+    ),
+
+    // These are various options for the listeners attached to the ModuleManager
+    'module_listener_options' => array(
+        // This should be an array of paths in which modules reside.
+        // If a string key is provided, the listener will consider that a module
+        // namespace, the value of that key the specific path to that module's
+        // Module class.
+        'module_paths' => array(
+            './module',
+            './vendor',
+        ),
+
+        // An array of paths from which to glob configuration files after
+        // modules are loaded. These effectively override configuration
+        // provided by modules themselves. Paths may use GLOB_BRACE notation.
+        'config_glob_paths' => array(
+            'config/autoload/{{,*.}global,{,*.}local}.php',
+        ),
+
+        // Whether or not to enable a configuration cache.
+        // If enabled, the merged configuration will be cached and used in
+        // subsequent requests.
+        //'config_cache_enabled' => $booleanValue,
+
+        // The key used to create the configuration cache file name.
+        //'config_cache_key' => $stringKey,
+
+        // Whether or not to enable a module class map cache.
+        // If enabled, creates a module class map cache which will be used
+        // by in future requests, to reduce the autoloading process.
+        //'module_map_cache_enabled' => $booleanValue,
+
+        // The key used to create the class map cache file name.
+        //'module_map_cache_key' => $stringKey,
+
+        // The path in which to cache merged configuration.
+        //'cache_dir' => $stringPath,
+
+        // Whether or not to enable modules dependency checking.
+        // Enabled by default, prevents usage of modules that depend on other modules
+        // that weren't loaded.
+        // 'check_dependencies' => true,
+    ),
+
+    // Used to create an own service manager. May contain one or more child arrays.
+    //'service_listener_options' => array(
+    //     array(
+    //         'service_manager' => $stringServiceManagerName,
+    //         'config_key'      => $stringConfigKey,
+    //         'interface'       => $stringOptionalInterface,
+    //         'method'          => $stringRequiredMethodName,
+    //     ),
+    // ),
+
+   // Initial configuration with which to seed the ServiceManager.
+   // Should be compatible with Zend\ServiceManager\Config.
+   // 'service_manager' => array(),
+);
diff --git a/pp3/config/autoload/.gitignore b/pp3/config/autoload/.gitignore
new file mode 100755
index 0000000..1a83fda
--- /dev/null
+++ b/pp3/config/autoload/.gitignore
@@ -0,0 +1,2 @@
+local.php
+*.local.php
diff --git a/pp3/config/autoload/README.md b/pp3/config/autoload/README.md
new file mode 100755
index 0000000..4e504db
--- /dev/null
+++ b/pp3/config/autoload/README.md
@@ -0,0 +1,8 @@
+About this directory:
+=====================
+
+By default, this application is configured to load all configs in
+`./config/autoload/{,*.}{global,local}.php`. Doing this provides a
+location for a developer to drop in configuration override files provided by
+modules, as well as cleanly provide individual, application-wide config files
+for things like database connections, etc.
diff --git a/pp3/config/autoload/global.php b/pp3/config/autoload/global.php
new file mode 100755
index 0000000..104762e
--- /dev/null
+++ b/pp3/config/autoload/global.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Global Configuration Override
+ *
+ * You can use this file for overriding configuration values from modules, etc.
+ * You would place values in here that are agnostic to the environment and not
+ * sensitive to security.
+ *
+ * @NOTE: In practice, this file will typically be INCLUDED in your source
+ * control, so do not include passwords or other sensitive information in this
+ * file.
+ */
+
+return array(
+    // ...
+);
diff --git a/pp3/config/autoload/local.php.dist b/pp3/config/autoload/local.php.dist
new file mode 100755
index 0000000..cc8154c
--- /dev/null
+++ b/pp3/config/autoload/local.php.dist
@@ -0,0 +1,14 @@
+<?php
+
+return array(
+  'doctrine' => array(
+    'connection' => array(
+      'orm_default' => array(
+        'driverClass' =>'Doctrine\DBAL\Driver\PDOMySql\Driver',
+        'params' => array(
+          'host'     => 'localhost',
+          'port'     => '3306',
+          'user'     => 'root',
+          'password' => 'root',
+          'dbname'   => 'pp3',
+)))));
\ No newline at end of file
diff --git a/pp3/config/autoupdate-catalog-2_6.dtd b/pp3/config/autoupdate-catalog-2_6.dtd
new file mode 100644
index 0000000..8ed5514
--- /dev/null
+++ b/pp3/config/autoupdate-catalog-2_6.dtd
@@ -0,0 +1,67 @@
+<!-- -//NetBeans//DTD Autoupdate Catalog 2.6//EN -->
+<!-- XML representation of Autoupdate Modules/Updates Catalog -->
+
+<!ELEMENT module_updates ((notification?, (module_group|module)*, license*)|error)>
+<!ATTLIST module_updates timestamp CDATA #REQUIRED>
+
+<!ELEMENT module_group ((module_group|module)*)>
+<!ATTLIST module_group name CDATA #REQUIRED>
+
+<!ELEMENT notification (#PCDATA)>
+<!ATTLIST notification url CDATA #IMPLIED>
+
+<!ELEMENT module (description?, module_notification?, external_package*, (manifest | l10n) )>
+<!ATTLIST module codenamebase CDATA #REQUIRED
+                 homepage     CDATA #IMPLIED
+                 distribution CDATA #REQUIRED
+                 license      CDATA #IMPLIED
+                 downloadsize CDATA #REQUIRED
+                 needsrestart (true|false) #IMPLIED
+                 moduleauthor CDATA #IMPLIED
+                 releasedate  CDATA #IMPLIED
+                 global       (true|false) #IMPLIED
+                 targetcluster CDATA #IMPLIED
+                 eager (true|false) #IMPLIED
+                 autoload (true|false) #IMPLIED>
+
+<!ELEMENT description (#PCDATA)>
+
+<!ELEMENT module_notification (#PCDATA)>
+
+<!ELEMENT external_package EMPTY>
+<!ATTLIST external_package
+                 name CDATA #REQUIRED
+                 target_name  CDATA #REQUIRED
+                 start_url    CDATA #REQUIRED
+                 description  CDATA #IMPLIED>
+
+<!ELEMENT manifest EMPTY>
+<!ATTLIST manifest OpenIDE-Module CDATA #REQUIRED
+                   OpenIDE-Module-Name CDATA #REQUIRED
+                   OpenIDE-Module-Specification-Version CDATA #REQUIRED
+                   OpenIDE-Module-Implementation-Version CDATA #IMPLIED
+                   OpenIDE-Module-Module-Dependencies CDATA #IMPLIED
+                   OpenIDE-Module-Package-Dependencies CDATA #IMPLIED
+                   OpenIDE-Module-Java-Dependencies CDATA #IMPLIED
+                   OpenIDE-Module-IDE-Dependencies CDATA #IMPLIED
+                   OpenIDE-Module-Short-Description CDATA #IMPLIED
+                   OpenIDE-Module-Long-Description CDATA #IMPLIED
+                   OpenIDE-Module-Display-Category CDATA #IMPLIED
+                   OpenIDE-Module-Provides CDATA #IMPLIED
+                   OpenIDE-Module-Requires CDATA #IMPLIED
+                   OpenIDE-Module-Recommends CDATA #IMPLIED
+                   OpenIDE-Module-Needs CDATA #IMPLIED
+                   AutoUpdate-Show-In-Client (true|false) #IMPLIED
+                   AutoUpdate-Essential-Module (true|false) #IMPLIED>
+
+<!ELEMENT l10n EMPTY>
+<!ATTLIST l10n   langcode             CDATA #IMPLIED
+                 brandingcode         CDATA #IMPLIED
+                 module_spec_version  CDATA #IMPLIED
+                 module_major_version CDATA #IMPLIED
+                 OpenIDE-Module-Name  CDATA #IMPLIED
+                 OpenIDE-Module-Long-Description CDATA #IMPLIED>
+
+<!ELEMENT license (#PCDATA)>
+<!ATTLIST license name CDATA #REQUIRED
+                  url  CDATA #IMPLIED>
diff --git a/pp3/config/erd.png b/pp3/config/erd.png
new file mode 100644
index 0000000..c80934c
Binary files /dev/null and b/pp3/config/erd.png differ
diff --git a/pp3/config/pp3.sql b/pp3/config/pp3.sql
new file mode 100644
index 0000000..03fdfd9
--- /dev/null
+++ b/pp3/config/pp3.sql
@@ -0,0 +1,165 @@
+-- phpMyAdmin SQL Dump
+-- version 4.8.3
+-- https://www.phpmyadmin.net/
+--
+-- Počítač: localhost
+-- Vytvořeno: Čtv 10. říj 2019, 13:57
+-- Verze serveru: 5.7.27-0ubuntu0.18.04.1
+-- Verze PHP: 5.6.40-12+ubuntu18.04.1+deb.sury.org+1
+
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET AUTOCOMMIT = 0;
+START TRANSACTION;
+SET time_zone = "+00:00";
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+--
+-- Databáze: `pp3`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Struktura tabulky `category`
+--
+
+CREATE TABLE IF NOT EXISTS `category` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Struktura tabulky `nb_version`
+--
+
+CREATE TABLE IF NOT EXISTS `nb_version` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `version` varchar(255) COLLATE utf8_czech_ci NOT NULL,
+  `verifiable` int(11) NOT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Struktura tabulky `nb_version_plugin_version`
+--
+
+CREATE TABLE IF NOT EXISTS `nb_version_plugin_version` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `nb_version_id` int(11) NOT NULL,
+  `plugin_version_id` int(11) NOT NULL,
+  `verification_id` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Struktura tabulky `plugin`
+--
+
+CREATE TABLE IF NOT EXISTS `plugin` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) COLLATE utf8_czech_ci NOT NULL,
+  `artifactid` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  `license` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  `author` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  `added_at` datetime DEFAULT CURRENT_TIMESTAMP,
+  `last_updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `approved_at` datetime DEFAULT NULL,
+  `url` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  `status` int(11) DEFAULT NULL,
+  `latest_version` varchar(11) COLLATE utf8_czech_ci DEFAULT NULL,
+  `release_version` varchar(11) COLLATE utf8_czech_ci DEFAULT NULL,
+  `description` text COLLATE utf8_czech_ci,
+  `short_description` text COLLATE utf8_czech_ci,
+  `image` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  `homepage` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  `downloads` int(11) DEFAULT NULL,
+  `groupid` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Struktura tabulky `plugin_category`
+--
+
+CREATE TABLE IF NOT EXISTS `plugin_category` (
+  `plugin_id` int(11) NOT NULL,
+  `category_id` int(11) NOT NULL,
+  PRIMARY KEY (`plugin_id`,`category_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Struktura tabulky `plugin_version`
+--
+
+CREATE TABLE IF NOT EXISTS `plugin_version` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `version` varchar(255) COLLATE utf8_czech_ci NOT NULL,
+  `url` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  `relnotes` text COLLATE utf8_czech_ci,
+  `plugin_id` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Struktura tabulky `verification`
+--
+
+CREATE TABLE IF NOT EXISTS `verification` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `status` int(11) DEFAULT NULL,
+  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
+  `plugin_version_id` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Struktura tabulky `verification_request`
+--
+
+CREATE TABLE IF NOT EXISTS `verification_request` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
+  `vote` int(11) DEFAULT NULL,
+  `voted_at` datetime DEFAULT NULL,
+  `comment` text COLLATE utf8_czech_ci,
+  `verification_id` int(11) DEFAULT NULL,
+  `verifier_id` int(11) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
+
+-- --------------------------------------------------------
+
+--
+-- Struktura tabulky `verifier`
+--
+
+CREATE TABLE IF NOT EXISTS `verifier` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `user_id` varchar(255) COLLATE utf8_czech_ci DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
+COMMIT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/pp3/init_autoloader.php b/pp3/init_autoloader.php
new file mode 100755
index 0000000..885703c
--- /dev/null
+++ b/pp3/init_autoloader.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * This autoloading setup is really more complicated than it needs to be for most
+ * applications. The added complexity is simply to reduce the time it takes for
+ * new developers to be productive with a fresh skeleton. It allows autoloading
+ * to be correctly configured, regardless of the installation method and keeps
+ * the use of composer completely optional. This setup should work fine for
+ * most users, however, feel free to configure autoloading however you'd like.
+ */
+
+// Composer autoloading
+if (file_exists('vendor/autoload.php')) {
+    $loader = include 'vendor/autoload.php';
+}
+
+if (class_exists('Zend\Loader\AutoloaderFactory')) {
+    return;
+}
+
+$zf2Path = false;
+
+if (getenv('ZF2_PATH')) {            // Support for ZF2_PATH environment variable
+    $zf2Path = getenv('ZF2_PATH');
+} elseif (get_cfg_var('zf2_path')) { // Support for zf2_path directive value
+    $zf2Path = get_cfg_var('zf2_path');
+}
+
+if ($zf2Path) {
+    if (isset($loader)) {
+        $loader->add('Zend', $zf2Path);
+        $loader->add('ZendXml', $zf2Path);
+    } else {
+        include $zf2Path . '/Zend/Loader/AutoloaderFactory.php';
+        Zend\Loader\AutoloaderFactory::factory(array(
+            'Zend\Loader\StandardAutoloader' => array(
+                'autoregister_zf' => true
+            )
+        ));
+    }
+}
+
+if (!class_exists('Zend\Loader\AutoloaderFactory')) {
+    throw new RuntimeException('Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.');
+}
diff --git a/pp3/module/Application/Module.php b/pp3/module/Application/Module.php
new file mode 100755
index 0000000..7021063
--- /dev/null
+++ b/pp3/module/Application/Module.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+namespace Application;
+
+use Zend\Mvc\ModuleRouteListener;
+use Zend\Mvc\MvcEvent;
+use Zend\Session\SessionManager;
+use Zend\Session\Config\SessionConfig;
+use Zend\Session\Container;
+
+class Module {
+
+    public function onBootstrap(MvcEvent $e) {
+        $eventManager = $e->getApplication()->getEventManager();
+        $moduleRouteListener = new ModuleRouteListener();
+        $moduleRouteListener->attach($eventManager);
+
+        $this->initSession([
+            'remember_me_seconds' => 180,
+            'use_cookies' => true,
+            //'cookie_httponly' => true,
+        ]);        
+    }
+
+    public function getConfig() {
+        return include __DIR__ . '/config/module.config.php';
+    }
+
+    public function getAutoloaderConfig() {
+        return array(
+            'Zend\Loader\StandardAutoloader' => array(
+                'namespaces' => array(
+                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
+                ),
+            ),
+        );
+    }
+
+    public function initSession($config) {
+        $sessionConfig = new SessionConfig();
+        $sessionConfig->setOptions($config);
+        $sessionManager = new SessionManager($sessionConfig);
+        $sessionManager->start();
+        Container::setDefaultManager($sessionManager);
+    }
+}
diff --git a/pp3/module/Application/config/.gitignore b/pp3/module/Application/config/.gitignore
new file mode 100755
index 0000000..48752b8
--- /dev/null
+++ b/pp3/module/Application/config/.gitignore
@@ -0,0 +1 @@
+module.config.php
\ No newline at end of file
diff --git a/pp3/module/Application/config/module.config.php.dist b/pp3/module/Application/config/module.config.php.dist
new file mode 100755
index 0000000..7687101
--- /dev/null
+++ b/pp3/module/Application/config/module.config.php.dist
@@ -0,0 +1,226 @@
+<?php
+
+// COPY THIS SAMPLE CPNFIG FILE OVER TO module.config.php to apply it
+
+//namespace Application;
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ */
+return array(   
+    'pp3' => array (
+        'mavenRepoUrl' => 'https://repo1.maven.org/maven2/',
+        'catalogSavepath' => '/home/honza/checkout/pp3/public/data',
+        'catalogUrlPath' => 'http://localhost/checkout/pp3/public/data',    
+        'dtdPath' => 'http://localhost/checkout/pp3/public/data/autoupdate-catalog-2_6.dtd',    
+        'admin' => array(
+            'jan.pirek@gmail.com',
+            'jiri.kovalsky@gmail.com'
+        )
+    ), 
+    'router' => array(
+        'routes' => array(  
+            'home' => array(
+                'type' => 'segment',
+                'options' => array(
+                    'route' => '/',
+                    'constraints' => array(
+                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
+                    ),
+                    'defaults' => array(
+                        '__NAMESPACE__' => 'Application\Controller',
+                        'controller' => 'Index',
+                        'action' => 'index',
+                    ),
+                ),                
+            ),
+            'catalogue' => array(
+                'type' => 'segment',
+                'options' => array(
+                    'route' => '/catalogue[/][:action]',
+                    'constraints' => array(
+                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
+                    ),
+                    'defaults' => array(
+                        '__NAMESPACE__' => 'Application\Controller',
+                        'controller' => 'Index',
+                        'action' => 'catalogue',
+                    ),
+                ),                
+            ),  
+            'home' => array(
+                'type' => 'segment',
+                'options' => array(
+                    'route' => '/',
+                    'constraints' => array(
+                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
+                    ),
+                    'defaults' => array(
+                        '__NAMESPACE__' => 'Application\Controller',
+                        'controller' => 'Index',
+                        'action' => 'index',
+                    ),
+                ),                
+            ),          
+            'plugin' => array(
+                'type' => 'segment',
+                'options' => array(
+                    'route' => '/plugin[/][:action]',
+                    'constraints' => array(
+                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
+                    ),
+                    'defaults' => array(
+                        '__NAMESPACE__' => 'Application\Controller',
+                        'controller' => 'Plugin',
+                        'action' => 'index',
+                    ),
+                ),                
+            ),   
+            'plugin-version' => array(
+                'type' => 'segment',
+                'options' => array(
+                    'route' => '/plugin-version[/][:action]',
+                    'constraints' => array(
+                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
+                    ),
+                    'defaults' => array(
+                        '__NAMESPACE__' => 'Application\Controller',
+                        'controller' => 'PluginVersion',
+                        'action' => 'index',
+                    ),
+                ),                
+            ),   
+            'verification' => array(
+                'type' => 'segment',
+                'options' => array(
+                    'route' => '/verification[/][:action]',
+                    'constraints' => array(
+                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
+                    ),
+                    'defaults' => array(
+                        '__NAMESPACE__' => 'Application\Controller',
+                        'controller' => 'Verification',
+                        'action' => 'index',
+                    ),
+                ),                
+            ),      
+            'admin' => array(
+                'type' => 'segment',
+                'options' => array(
+                    'route' => '/admin[/][:action]',
+                    'constraints' => array(
+                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
+                    ),
+                    'defaults' => array(
+                        '__NAMESPACE__' => 'Application\Controller',
+                        'controller' => 'Admin',
+                        'action' => 'index',
+                    ),
+                ),                
+            ), 
+            'login' => array(
+                'type' => 'segment',
+                'options' => array(
+                    'route' => '/login[/][:action]',
+                    'constraints' => array(
+                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
+                    ),
+                    'defaults' => array(
+                        '__NAMESPACE__' => 'Application\Controller',
+                        'controller' => 'Login',
+                        'action' => 'request',
+                    ),
+                ),                
+            ),       
+        ),
+    ),
+    'service_manager' => array(
+        'abstract_factories' => array(
+            'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
+            'Zend\Log\LoggerAbstractServiceFactory',
+        ),
+        'factories' => array(
+            'translator' => 'Zend\Mvc\Service\TranslatorServiceFactory',
+            'doctrine.cache.mycache' => function ($sm) {
+                $cache = new \Doctrine\Common\Cache\ApcuCache();
+                return $cache;
+            },
+        ),
+        'alias' => array(
+            'Zend\Authentication\AuthenticationService' => 'my_auth_service',
+        ),
+        'invokables' => array(
+            'my_auth_service' => 'Zend\Authentication\AuthenticationService'
+        ),
+        'services' => array(
+            'paginator' => new Knp\Component\Pager\Paginator(),
+        )
+    ),
+    'translator' => array(
+        'locale' => 'en_US',
+        'translation_file_patterns' => array(
+            array(
+                'type' => 'gettext',
+                'base_dir' => __DIR__ . '/../language',
+                'pattern' => '%s.mo',
+            ),
+        ),
+    ),
+    'controllers' => [
+        'factories' => [
+            // Update the following line:
+            'Application\Controller\Index' => 'Application\Factory\IndexControllerFactory',
+            'Application\Controller\Login' => 'Application\Factory\LoginControllerFactory',
+            'Application\Controller\Plugin' => 'Application\Factory\PluginControllerFactory',
+            'Application\Controller\PluginVersion' => 'Application\Factory\PluginVersionControllerFactory',
+            'Application\Controller\Verification' => 'Application\Factory\VerificationControllerFactory',
+            'Application\Controller\Admin' => 'Application\Factory\AdminControllerFactory',
+        ],
+    ],
+    'view_manager' => array(
+        'display_not_found_reason' => true,
+        'display_exceptions' => true,
+        'doctype' => 'HTML5',
+        'not_found_template' => 'error/404',
+        'exception_template' => 'error/index',
+        'template_map' => array(
+            'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
+            'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',
+            'error/404' => __DIR__ . '/../view/error/404.phtml',
+            'error/index' => __DIR__ . '/../view/error/index.phtml',
+        ),
+        'template_path_stack' => array(
+            __DIR__ . '/../view',
+        ),
+    ),
+    // Placeholder for console routes
+    'console' => array(
+        'router' => array(
+            'routes' => array(
+            ),
+        ),
+    ),
+    // doctrine
+    'doctrine' => array(
+        'driver' => array(
+            'application_entities' => array(
+                'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
+                'paths' => array(__DIR__ . '/../src/Application/Entity')
+            ),
+            'orm_default' => array(             
+                'drivers' => array(
+                    'Application\Entity' => 'application_entities'
+                )
+            )),
+        'configuration' => array(
+                'orm_default' => array(
+                   'metadata_cache'    => 'array',
+                   'query_cache'       => 'array',
+                   'result_cache'      => 'array',
+                )
+            ),
+        ),
+);
diff --git a/pp3/module/Application/language/cs_CZ.mo b/pp3/module/Application/language/cs_CZ.mo
new file mode 100755
index 0000000..552e3ef
Binary files /dev/null and b/pp3/module/Application/language/cs_CZ.mo differ
diff --git a/pp3/module/Application/language/cs_CZ.po b/pp3/module/Application/language/cs_CZ.po
new file mode 100755
index 0000000..4802642
--- /dev/null
+++ b/pp3/module/Application/language/cs_CZ.po
@@ -0,0 +1,153 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: ZendSkeletonApplication\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-07-05 22:17-0700\n"
+"PO-Revision-Date: 2012-07-06 13:05+0100\n"
+"Last-Translator: David Lukas <da...@zfdaily.com>\n"
+"Language-Team: ZF Contibutors <zf...@zend.com>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-KeywordsList: translate\n"
+"X-Poedit-Language: Czech\n"
+"X-Poedit-Country: CZECH REPUBLIC\n"
+"X-Poedit-Basepath: .\n"
+"X-Poedit-SearchPath-0: ..\n"
+
+#: ../view/layout/layout.phtml:6
+#: ../view/layout/layout.phtml:33
+msgid "Skeleton Application"
+msgstr "Skeleton aplikace"
+
+#: ../view/layout/layout.phtml:36
+msgid "Home"
+msgstr "Úvod"
+
+#: ../view/layout/layout.phtml:50
+msgid "All rights reserved."
+msgstr "Všechna práva vyhrazena."
+
+#: ../view/application/index/index.phtml:2
+#, php-format
+msgid "Welcome to %sZend Framework 2%s"
+msgstr "Vítejte v %sZend Framework 2%s"
+
+#: ../view/application/index/index.phtml:3
+#, php-format
+msgid "Congratulations! You have successfully installed the %sZF2 Skeleton Application%s. You are currently running Zend Framework version %s. This skeleton can serve as a simple starting point for you to begin building your application on ZF2."
+msgstr "Blahopřejeme! Úspěšně jste nainstalovali %sZF2 Skeleton Application%s. Právě používáte Zend Framework verze %s. Tato kostra aplikace vám poslouží jako jednoduchý výchozí bod, ze kterého můžete vyjít při tvorbě vlastní aplikace nad ZF2."
+
+#: ../view/application/index/index.phtml:4
+msgid "Fork Zend Framework 2 on GitHub"
+msgstr "Fork Zend Framework 2 na GitHub"
+
+#: ../view/application/index/index.phtml:10
+msgid "Follow Development"
+msgstr "Sledujte vývoj"
+
+#: ../view/application/index/index.phtml:11
+#, php-format
+msgid "Zend Framework 2 is under active development. If you are interested in following the development of ZF2, there is a special ZF2 portal on the official Zend Framework website which provides links to the ZF2 %swiki%s, %sdev blog%s, %sissue tracker%s, and much more. This is a great resource for staying up to date with the latest developments!"
+msgstr "Zend Framework 2 je aktivně vyvíjen. Chcete-li sledovat vývoj ZF2, máte na oficiálních webových stránkách Zend Framework k dispozici zvláštní portál ZF2, na kterém najdete odkazy na ZF2 %swiki%s, %svývojářský blog%s, %sissue tracker%s a mnoho dalšího. Tento portál je skvělý zdroj aktuálních informací o nejnovějším vývoji!"
+
+#: ../view/application/index/index.phtml:12
+msgid "ZF2 Development Portal"
+msgstr "Vývojářský portál ZF2"
+
+#: ../view/application/index/index.phtml:16
+msgid "Discover Modules"
+msgstr "Objevte Moduly"
+
+#: ../view/application/index/index.phtml:17
+#, php-format
+msgid "The community is working on developing a community site to serve as a repository and gallery for ZF2 modules. The project is available %son GitHub%s. The site is currently live and currently contains a list of some of the modules already available for ZF2."
+msgstr "Komunita pracuje na vývoji komunitního webu, který bude sloužit jako archiv a galerie modulů ZF2. Tento projekt je dostupný %sna GitHub%s. Web je aktuálně v provozu a obsahuje seznam některých již dostupných modulů ZF2."
+
+#: ../view/application/index/index.phtml:18
+msgid "Explore ZF2 Modules"
+msgstr "Prozkoumejte Moduly ZF2"
+
+#: ../view/application/index/index.phtml:22
+msgid "Help &amp; Support"
+msgstr "Pomoc &amp; Podpora"
+
+#: ../view/application/index/index.phtml:23
+#, php-format
+msgid "If you need any help or support while developing with ZF2, you may reach us via IRC: %s#zftalk on Freenode%s. We'd love to hear any questions or feedback you may have regarding the beta releases. Alternatively, you may subscribe and post questions to the %smailing lists%s."
+msgstr "Budete-li při vývoji se ZF2 potřebovat jakoukoli pomoc nebo podporu, můžete nás zastihnout přes IRC: %s#zftalk na Freenode%s. Budeme rádi za jakékoli vaše otázky nebo připomínky týkající se beta verzí. Případně se také můžete přihlásit k odběru a posílat otázky na naše %se-mailové distribuční seznamy%s."
+
+#: ../view/application/index/index.phtml:24
+msgid "Ping us on IRC"
+msgstr "Ozvěte se nám na IRC"
+
+#: ../view/error/index.phtml:1
+msgid "An error occurred"
+msgstr "Vyskytla se chyba"
+
+#: ../view/error/index.phtml:8
+msgid "Additional information"
+msgstr "Další informace"
+
+#: ../view/error/index.phtml:11
+#: ../view/error/index.phtml:35
+msgid "File"
+msgstr "Soubor"
+
+#: ../view/error/index.phtml:15
+#: ../view/error/index.phtml:39
+msgid "Message"
+msgstr "Zpráva"
+
+#: ../view/error/index.phtml:19
+#: ../view/error/index.phtml:43
+#: ../view/error/404.phtml:55
+msgid "Stack trace"
+msgstr "Trasování zásobníku (Stack trace)"
+
+#: ../view/error/index.phtml:29
+msgid "Previous exceptions"
+msgstr "Předchozí výjimky"
+
+#: ../view/error/index.phtml:58
+msgid "No Exception available"
+msgstr "Žádná výjimka není k dispozici"
+
+#: ../view/error/404.phtml:1
+msgid "A 404 error occurred"
+msgstr "Vyskytla se chyba 404"
+
+#: ../view/error/404.phtml:10
+msgid "The requested controller was unable to dispatch the request."
+msgstr "Požadovaný controller nemohl vyřídit požadavek."
+
+#: ../view/error/404.phtml:13
+msgid "The requested controller could not be mapped to an existing controller class."
+msgstr "Požadovaný controller se nepodařilo namapovat na žádnou existující třídu controlleru."
+
+#: ../view/error/404.phtml:16
+msgid "The requested controller was not dispatchable."
+msgstr "Požadovaný controller nepodporuje vyřízení (controller not dispatchable)."
+
+#: ../view/error/404.phtml:19
+msgid "The requested URL could not be matched by routing."
+msgstr "S požadovaným URL nebyla při směrování (routing) nalezena shoda."
+
+#: ../view/error/404.phtml:22
+msgid "We cannot determine at this time why a 404 was generated."
+msgstr "Momentálně nedokážeme určit, proč byla vygenerována chyba 404."
+
+#: ../view/error/404.phtml:34
+msgid "Controller"
+msgstr "Controller"
+
+#: ../view/error/404.phtml:41
+#, php-format
+msgid "resolves to %s"
+msgstr "je mapován na %s"
+
+#: ../view/error/404.phtml:51
+msgid "Exception"
+msgstr "Výjimka"
+
diff --git a/pp3/module/Application/language/en_US.mo b/pp3/module/Application/language/en_US.mo
new file mode 100755
index 0000000..972a28a
Binary files /dev/null and b/pp3/module/Application/language/en_US.mo differ
diff --git a/pp3/module/Application/language/en_US.po b/pp3/module/Application/language/en_US.po
new file mode 100755
index 0000000..b5e5f81
--- /dev/null
+++ b/pp3/module/Application/language/en_US.po
@@ -0,0 +1,153 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: ZendSkeletonApplication\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-07-05 22:17-0700\n"
+"PO-Revision-Date: 2012-07-05 22:17-0700\n"
+"Last-Translator: Evan Coury <me...@evancoury.com>\n"
+"Language-Team: ZF Contibutors <zf...@zend.com>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-KeywordsList: translate\n"
+"X-Poedit-Language: English\n"
+"X-Poedit-Country: UNITED STATES\n"
+"X-Poedit-Basepath: .\n"
+"X-Poedit-SearchPath-0: ..\n"
+
+#: ../view/layout/layout.phtml:6
+#: ../view/layout/layout.phtml:33
+msgid "Skeleton Application"
+msgstr ""
+
+#: ../view/layout/layout.phtml:36
+msgid "Home"
+msgstr ""
+
+#: ../view/layout/layout.phtml:50
+msgid "All rights reserved."
+msgstr ""
+
+#: ../view/application/index/index.phtml:2
+#, php-format
+msgid "Welcome to %sZend Framework 2%s"
+msgstr ""
+
+#: ../view/application/index/index.phtml:3
+#, php-format
+msgid "Congratulations! You have successfully installed the %sZF2 Skeleton Application%s. You are currently running Zend Framework version %s. This skeleton can serve as a simple starting point for you to begin building your application on ZF2."
+msgstr ""
+
+#: ../view/application/index/index.phtml:4
+msgid "Fork Zend Framework 2 on GitHub"
+msgstr ""
+
+#: ../view/application/index/index.phtml:10
+msgid "Follow Development"
+msgstr ""
+
+#: ../view/application/index/index.phtml:11
+#, php-format
+msgid "Zend Framework 2 is under active development. If you are interested in following the development of ZF2, there is a special ZF2 portal on the official Zend Framework website which provides links to the ZF2 %swiki%s, %sdev blog%s, %sissue tracker%s, and much more. This is a great resource for staying up to date with the latest developments!"
+msgstr ""
+
+#: ../view/application/index/index.phtml:12
+msgid "ZF2 Development Portal"
+msgstr ""
+
+#: ../view/application/index/index.phtml:16
+msgid "Discover Modules"
+msgstr ""
+
+#: ../view/application/index/index.phtml:17
+#, php-format
+msgid "The community is working on developing a community site to serve as a repository and gallery for ZF2 modules. The project is available %son GitHub%s. The site is currently live and currently contains a list of some of the modules already available for ZF2."
+msgstr ""
+
+#: ../view/application/index/index.phtml:18
+msgid "Explore ZF2 Modules"
+msgstr ""
+
+#: ../view/application/index/index.phtml:22
+msgid "Help &amp; Support"
+msgstr ""
+
+#: ../view/application/index/index.phtml:23
+#, php-format
+msgid "If you need any help or support while developing with ZF2, you may reach us via IRC: %s#zftalk on Freenode%s. We'd love to hear any questions or feedback you may have regarding the beta releases. Alternatively, you may subscribe and post questions to the %smailing lists%s."
+msgstr ""
+
+#: ../view/application/index/index.phtml:24
+msgid "Ping us on IRC"
+msgstr ""
+
+#: ../view/error/index.phtml:1
+msgid "An error occurred"
+msgstr ""
+
+#: ../view/error/index.phtml:8
+msgid "Additional information"
+msgstr ""
+
+#: ../view/error/index.phtml:11
+#: ../view/error/index.phtml:35
+msgid "File"
+msgstr ""
+
+#: ../view/error/index.phtml:15
+#: ../view/error/index.phtml:39
+msgid "Message"
+msgstr ""
+
+#: ../view/error/index.phtml:19
+#: ../view/error/index.phtml:43
+#: ../view/error/404.phtml:55
+msgid "Stack trace"
+msgstr ""
+
+#: ../view/error/index.phtml:29
+msgid "Previous exceptions"
+msgstr ""
+
+#: ../view/error/index.phtml:58
+msgid "No Exception available"
+msgstr ""
+
+#: ../view/error/404.phtml:1
+msgid "A 404 error occurred"
+msgstr ""
+
+#: ../view/error/404.phtml:10
+msgid "The requested controller was unable to dispatch the request."
+msgstr ""
+
+#: ../view/error/404.phtml:13
+msgid "The requested controller could not be mapped to an existing controller class."
+msgstr ""
+
+#: ../view/error/404.phtml:16
+msgid "The requested controller was not dispatchable."
+msgstr ""
+
+#: ../view/error/404.phtml:19
+msgid "The requested URL could not be matched by routing."
+msgstr ""
+
+#: ../view/error/404.phtml:22
+msgid "We cannot determine at this time why a 404 was generated."
+msgstr ""
+
+#: ../view/error/404.phtml:34
+msgid "Controller"
+msgstr ""
+
+#: ../view/error/404.phtml:41
+#, php-format
+msgid "resolves to %s"
+msgstr ""
+
+#: ../view/error/404.phtml:51
+msgid "Exception"
+msgstr ""
+
diff --git a/pp3/module/Application/src/Application/Controller/AdminController.php b/pp3/module/Application/src/Application/Controller/AdminController.php
new file mode 100644
index 0000000..03defb9
--- /dev/null
+++ b/pp3/module/Application/src/Application/Controller/AdminController.php
@@ -0,0 +1,397 @@
+<?php
+
+namespace Application\Controller;
+
+use Application\Controller\BaseController;
+use Zend\View\Model\ViewModel;
+use Application\Entity\Plugin;
+use Zend\Session\Container;
+use Application\Pp\MavenDataLoader;
+use Application\Pp\Catalog;
+use Application\Entity\Verifier;
+use Application\Entity\NbVersion;
+use Application\Entity\Category;
+use Zend\Mvc\MvcEvent;
+use HTMLPurifier;
+use HTMLPurifier_Config;
+use Zend\Http\Response;
+
+class AdminController extends BaseController {
+
+    private $_pluginRepository;
+    private $_pluginVersionRepository;
+    private $_nbVersionPluginVersionRepository;
+    private $_verificationRepository;
+    private $_verifierRepository;
+    private $_verificationRequestRepository;
+    private $_nbVersionRepository;
+    private $_categoryRepository;
+
+    public function __construct($pluginRepository, $nbVersionPluginVersionRepo, $verificationRepo, 
+                                $verifierRepository, $verificationRequestRepository, $nbVersionRepository,
+                                $pluginVersionRepository, $config, $categoryRepository) {
+        parent::__construct($config);
+        $this->_pluginRepository = $pluginRepository;
+        $this->_pluginVersionRepository = $pluginVersionRepository;
+        $this->_nbVersionPluginVersionRepository = $nbVersionPluginVersionRepo;
+        $this->_verificationRepository = $verificationRepo;
+        $this->_verifierRepository = $verifierRepository;
+        $this->_verificationRequestRepository = $verificationRequestRepository;
+        $this->_nbVersionRepository = $nbVersionRepository;
+        $this->_categoryRepository = $categoryRepository;
+    } 
+
+    public function deletePendingAction() {
+        $this->_checkAdminUser();
+        $pId = $this->params()->fromQuery('id');
+        if (!empty($pId)) {
+            $plugin = $this->_pluginRepository->find($pId);
+            if ($plugin) {
+                $this->_pluginRepository->remove($plugin);
+                $this->flashMessenger()->setNamespace('success')->addMessage('Plugin '.$plugin->getName().' removed');                
+            }        
+        }
+        return $this->redirect()->toRoute('admin', array(
+            'action' => 'approve'
+        ));
+    }
+
+    public function approveAction() {
+        $this->_checkAdminUser();
+        $pId = $this->params()->fromQuery('id');
+        if (!empty($pId)) {
+            $plugin = $this->_pluginRepository->find($pId);
+            if ($plugin) {
+                $plugin->setStatus(Plugin::STATUS_PUBLIC);
+                $plugin->setApprovedAt(new \DateTime('now'));
+                $this->_pluginRepository->persist($plugin);
+                $this->flashMessenger()->setNamespace('success')->addMessage('Plugin '.$plugin->getName().' approved');
+                return $this->redirect()->toRoute('admin', array(
+                    'action' => 'approve'
+                ));
+            }        
+        }
+        return new ViewModel([
+            'plugins' => $this->_pluginRepository->getPluginsByStatus(Plugin::STATUS_PRIVATE),
+        ]);
+    }
+
+    public function indexAction() {
+        $this->_checkAdminUser();
+        $plugins = null;
+        $search = null;
+        $req = $this->request;        
+        if ($this->params()->fromQuery('search')) {
+            $search = $this->params()->fromQuery('search');
+            $plugins = $this->_pluginRepository->getPluginsByName($search);
+        }
+        $pId = $this->params()->fromQuery('id');
+        $act = $this->params()->fromQuery('act');
+        $q = $this->params()->fromQuery('q');
+        if (!empty($pId)) {
+            $plugin = $this->_pluginRepository->find($pId);
+            if ($plugin) {
+                $plugins = array($plugin);
+            }
+            if ($act) {
+                switch ($act) {
+                    case 'publish':
+                        $plugin->setStatus(Plugin::STATUS_PUBLIC);
+                        $plugin->setApprovedAt(new \DateTime('now'));
+                        $this->_pluginRepository->persist($plugin);
+                        $this->flashMessenger()->setNamespace('success')->addMessage('Plugin '.$plugin->getName().' approved.');            
+                        break;
+                    case 'hide':
+                        $plugin->setStatus(Plugin::STATUS_PRIVATE);
+                        $this->_pluginRepository->persist($plugin);
+                        $this->flashMessenger()->setNamespace('success')->addMessage('Plugin '.$plugin->getName().' made hidden.');            
+                        break;
+                    case 'sync':
+                        $plugin->setDataLoader(new MavenDataLoader());
+                        try {
+                            $plugin->reloadData();
+                            $this->_pluginRepository->persist($plugin);            
+                            $this->flashMessenger()->setNamespace('success')->addMessage('Plugin data reloaded from maven-metadata.xml file.');            
+                        } catch (\Exception $e) {
+                            // maven-metadata.xml not found
+                            $this->flashMessenger()->setNamespace('error')->addMessage('Sorry, maven-metadata.xml file is missing.');                
+                        }
+                        break;
+                    case 'delete':
+                        $this->_pluginRepository->remove($plugin);
+                        $this->flashMessenger()->setNamespace('success')->addMessage('Plugin '.$plugin->getName().' deleted.');
+                        return $this->redirect()->toRoute('admin', array(
+                            'action' => 'index'
+                        ));
+                        break;
+                }
+            }
+        }
+        return new ViewModel([
+            'plugins' => $plugins,
+            'search' => $search,
+        ]);
+    }
+    
+    public function catalogAction() {
+        $this->_checkAdminUser();
+        $version = $this->params()->fromQuery('version');
+        $experimental = $this->params()->fromQuery('experimental');
+        if (!empty($version)) {        
+            $nbv = $this->_nbVersionRepository->findOneBy('version', $version);
+            if ($nbv) {
+                $items = $experimental ? $this->_pluginVersionRepository->getNonVerifiedVersionsByNbVersion($version) : $this->_pluginVersionRepository->getVerifiedVersionsByNbVersion($version);
+                if (count($items)) {                
+                    $catalog = new Catalog($version, $items, $experimental, $this->_config['pp3']['dtdPath'], $this->_getCatalogLink());
+                    try {
+                        $xml = $catalog->asXml(true);
+                        $catalog->storeXml($this->_config['pp3']['catalogSavepath'], $xml);
+                        $this->flashMessenger()->setNamespace('success')->addMessage('Catalog for NB '.$version.' published. Found '.count($items).' plugins.');
+                    } catch (\Exception $e){
+                        $this->flashMessenger()->setNamespace('error')->addMessage($e->getMessage());                        
+                    }                
+                } else {
+                    $this->flashMessenger()->setNamespace('info')->addMessage('No plugins foud for version NB '.$version);
+                }
+                return $this->redirect()->toRoute('admin', array(
+                    'action' => 'catalog'
+                ));
+            }    
+        }
+
+        return new ViewModel([
+            'catalUrlPath' => $this->_config['pp3']['catalogUrlPath'],
+            'nbVersions' => $this->_nbVersionRepository->findAll(),            
+        ]);
+    }
+
+    public function verifiersAction() {
+        $this->_checkAdminUser();
+        $req = $this->request;   
+        $id = $this->params()->fromQuery('id');
+        if (!empty($id)) {
+            $verifier = $this->_verifierRepository->find($id);
+            if ($verifier) {
+                $this->_verifierRepository->remove($verifier);$this->flashMessenger()->setNamespace('success')->addMessage('Verifier '.$verifier->getUserId().' deleted.');
+                return $this->redirect()->toRoute('admin', array(
+                    'action' => 'verifiers'
+                ));
+            }
+        }
+        if ($req->isPost() && $this->params()->fromPost('userId')) {
+            $verifier = new Verifier();
+            $verifier->setUserId($this->params()->fromPost('userId'));
+            $this->_verifierRepository->persist($verifier);
+            $this->flashMessenger()->setNamespace('success')->addMessage('Verifier '.$verifier->getUserId().' added.');
+                return $this->redirect()->toRoute('admin', array(
+                    'action' => 'verifiers'
+                ));
+        }
+        return new ViewModel([
+            'verifiers' => $this->_verifierRepository->findAll()
+        ]);
+    }
+
+    public function categoriesAction() {
+        $this->_checkAdminUser();
+        $req = $this->request;   
+        $id = $this->params()->fromQuery('id');
+        if (!empty($id)) {
+            $cat = $this->_categoryRepository->find($id);
+            if ($cat) {
+                $this->_categoryRepository->remove($cat);
+                $this->flashMessenger()->setNamespace('success')->addMessage('Category '.$cat->getName().' deleted.');
+                return $this->redirect()->toRoute('admin', array(
+                    'action' => 'categories'
+                ));
+            }
+        }
+        if ($req->isPost() && $this->params()->fromPost('name')) {
+            $cat = new Category();
+            $cat->setName($this->params()->fromPost('name'));
+            $this->_categoryRepository->persist($cat);
+            $this->flashMessenger()->setNamespace('success')->addMessage('Category '.$cat->getName().' added.');
+                return $this->redirect()->toRoute('admin', array(
+                    'action' => 'categories'
+                ));
+        }
+        return new ViewModel([
+            'categories' => $this->_categoryRepository->getAllCategoriesSortByName()
+        ]);
+    }
+
+    public function nbVersionsAction() {
+        $this->_checkAdminUser();
+        $req = $this->request;   
+        $id = $this->params()->fromQuery('id');
+        if (!empty($id)) {
+            $nbVersion = $this->_nbVersionRepository->find($id);
+            if ($nbVersion) {
+                $this->_nbVersionRepository->remove($nbVersion);
+                $this->_nbVersionPluginVersionRepository->removeByNbVersionId($id);
+                $this->flashMessenger()->setNamespace('success')->addMessage('NetBeans Version '.$nbVersion->getVersion().' deleted.');
+                return $this->redirect()->toRoute('admin', array(
+                    'action' => 'nbVersions'
+                ));
+            }
+        }
+        if ($req->isPost() && $this->params()->fromPost('version')) {
+            $nbVersion = new NbVersion();
+            $nbVersion->setVersion($this->params()->fromPost('version'));
+            $nbVersion->setVerifiable(NbVersion::VERIFIABLE_YES);
+            $this->_nbVersionRepository->persist($nbVersion);
+            $this->_symlinkLatestVersion($nbVersion);
+            $this->_createEmptyCatalogForNbVersion($nbVersion);
+            $this->flashMessenger()->setNamespace('success')->addMessage('NetBeans Version '.$nbVersion->getVersion().' added.');
+                return $this->redirect()->toRoute('admin', array(
+                    'action' => 'nbVersions'
+                ));
+        }
+        return new ViewModel([
+            'nbVersions' => $this->_nbVersionRepository->findAll()
+        ]);;
+    }
+
+    private function _createEmptyCatalogForNbVersion($nbVersion) {
+        $catalog = new Catalog($nbVersion->getVersion(), array(), false, $this->_config['pp3']['dtdPath'], $this->_getCatalogLink());
+        $catalogExp = new Catalog($nbVersion->getVersion(), array(), true, $this->_config['pp3']['dtdPath'], $this->_getCatalogLink());
+        try {
+            $xml = $catalog->asXml(true);
+            $xmlExp = $catalogExp->asXml(true);
+            $catalog->storeXml($this->_config['pp3']['catalogSavepath'], $xml);
+            $catalogExp->storeXml($this->_config['pp3']['catalogSavepath'], $xmlExp);
+        } catch (\Exception $e){
+            $this->flashMessenger()->setNamespace('error')->addMessage($e->getMessage());                        
+        }         
+    }
+
+    private function _symlinkLatestVersion($nbVersion) {
+        $link = $this->_config['pp3']['catalogSavepath'].'/latest';
+        $target = $this->_config['pp3']['catalogSavepath'].'/'.$nbVersion->getVersion();        
+        if (is_link($link)) {
+            unlink($link);
+        }
+        symlink($target, $link);
+    }
+
+    private function _getCatalogLink() {
+        return $_SERVER["REQUEST_SCHEME"].'://'.$_SERVER["HTTP_HOST"].$this->url()->fromRoute('catalogue', array('action' => 'download')).'?id=';
+    }
+
+    private function _checkAdminUser() {
+        if (!$this->_isAdmin) {
+            return $this->redirect()->toRoute('plugin', array(
+                'action' => 'index'
+            ));
+        }
+    }
+
+    public function editAction() {
+        $this->_checkAdminUser();
+        $pId = $this->params()->fromQuery('id');
+        $plugin = $this->_pluginRepository->find($pId);        
+        if (!$plugin || empty($pId)) {
+            return $this->redirect()->toRoute('admin');
+        }
+        $req = $this->request;
+        if ($req->isPost()) {
+            $validatedData = $this->_validateAndCleanPluginData(
+                $this->params()->fromPost('author'),
+                $this->params()->fromPost('name'),
+                $this->params()->fromPost('license'),
+                $this->params()->fromPost('description'),
+                $this->params()->fromPost('short_description'),
+                $this->params()->fromPost('category')
+            );
+            if ($validatedData) {
+                $plugin->setAuthor($validatedData['author']);
+                $plugin->setName($validatedData['name']);
+                $plugin->setLicense($validatedData['license']);
+                $plugin->setDescription($validatedData['description']);
+                $plugin->setShortDescription($validatedData['short_description']);
+                $plugin->setLastUpdatedAt(new \DateTime('now'));                
+
+                // save image
+                $im = $this->handleImgUpload($this->_config['pp3']['catalogSavepath'].'/plugins/'.$plugin->getId());
+                if ($im) {                    
+                    $plugin->setImage($im);
+                }
+
+
+                // categ
+                $plugin->removeCategories();
+                $this->_pluginRepository->persist($plugin);
+                $cat = $this->_categoryRepository->find($validatedData['category']);
+                if ($cat) {
+                    $plugin->addCategory($cat);
+                }
+                $cat2 = $this->params()->fromPost('category2');
+                if ($cat2 && (!$cat || ($cat2 != $cat->getId()))) {
+                    $cat2 = $this->_categoryRepository->find($this->params()->fromPost('category2'));
+                    if ($cat2) {
+                        //die(var_dump($cat2, $plugin->getCategories()[1], $validatedData['category']));
+                        $plugin->addCategory($cat2);
+                    }
+                }
+
+                $this->_pluginRepository->persist($plugin);
+                $this->flashMessenger()->setNamespace('success')->addMessage('Plugin updated.');               
+            } else {
+                $this->flashMessenger()->setNamespace('error')->addMessage('Missing required data or Author email not in correct format.');
+            }
+            return $this->redirect()->toUrl('./edit?id='.$plugin->getId());      
+        }
+
+        return new ViewModel(array(
+            'plugin' => $plugin,
+            'categories' => $this->_categoryRepository->getAllCategoriesSortByName(),
+        ));
+    }
+
+    private function _validateAndCleanPluginData($author, $name, $license, $description, $shortDescription, $category) {
+        if (empty($author) || empty($name) || empty($license) || empty($category) || empty($shortDescription)
+            || !filter_var($author, FILTER_VALIDATE_EMAIL)) {
+            return false;
+        }
+        $config = HTMLPurifier_Config::createDefault();
+        $purifier = new HTMLPurifier($config);
+        return  array(
+            'author' => $purifier->purify($author),
+            'name' => $purifier->purify($name),
+            'license' => $purifier->purify($license),
+            'description' => $purifier->purify($description),
+            'short_description' => $purifier->purify($shortDescription),
+            'category' => $category
+        );
+    }
+
+    public function searchAutocompleteAction() {
+        $this->_checkAdminUser();        
+        $term = $this->params()->fromQuery('term');
+        $a = array();
+        $response = $this->getResponse();
+        if (!empty($term)) {
+            $plugins = $this->_pluginRepository->getPluginsByName($term);
+            if (!empty($plugins)) {
+                foreach ($plugins as $p) {
+                    $a[] = array('label' => $p->getName(), 'value' => $p->getName());
+                }
+                $response->setContent(json_encode($a));
+            }
+        }
+        return $response;
+    }
+
+    private function handleImgUpload($imgFolder) {
+        $tmp_name = $_FILES["image-file"]["tmp_name"];
+        // basename() may prevent filesystem traversal attacks;
+        // further validation/sanitation of the filename may be appropriate
+        $name = basename($_FILES["image-file"]["name"]);
+        if(!file_exists($imgFolder)) {
+            mkdir($imgFolder, 0777, true);
+        }
+        if(move_uploaded_file($tmp_name, $imgFolder.'/'.$name)) {
+            return $name; 
+        }        
+    }
+}
diff --git a/pp3/module/Application/src/Application/Controller/BaseController.php b/pp3/module/Application/src/Application/Controller/BaseController.php
new file mode 100644
index 0000000..3ea84e1
--- /dev/null
+++ b/pp3/module/Application/src/Application/Controller/BaseController.php
@@ -0,0 +1,44 @@
+<?php
+
+
+namespace Application\Controller;
+
+use Zend\Mvc\Controller\AbstractActionController;
+use Zend\Session\Container;
+use Zend\Mvc\MvcEvent;
+
+define('ANONUSER', 'Anonymous');
+
+class BaseController extends AbstractActionController {
+
+    protected $_session;
+    protected $_config;
+    protected $_isAdmin;
+    protected $_sessionUserId;
+    
+    public function __construct($config) {
+        $this->_config = $config;
+        $this->_session = new Container();
+    }
+    
+    public function onDispatch(MvcEvent $e) {
+        if (!$this->isAuthenticated()) {
+            return $this->redirect()->toRoute('home', array(
+                'action' => 'index'
+            ));
+        }
+        $this->_sessionUserId = $_SESSION['sessionUserId'];
+        $this->layout()->setVariable('sessionUserId', $this->_sessionUserId);
+        $this->isAdmin();
+        return parent::onDispatch($e);
+    }
+
+    private function isAuthenticated() {
+        return !empty($_SESSION['sessionUserId']);
+    }
+    
+    private function isAdmin() {
+        $this->_isAdmin = $_SESSION['isAdmin'];        
+        $this->layout()->setVariable('isAdmin', $this->_isAdmin);
+    }
+}
\ No newline at end of file
diff --git a/pp3/module/Application/src/Application/Controller/IndexController.php b/pp3/module/Application/src/Application/Controller/IndexController.php
new file mode 100755
index 0000000..9397657
--- /dev/null
+++ b/pp3/module/Application/src/Application/Controller/IndexController.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Application\Controller;
+
+use Zend\Mvc\Controller\AbstractActionController;
+use Knp\Component\Pager\PaginatorInterface;
+use Zend\View\Model\ViewModel;
+use DoctrineORMModule\Paginator\Adapter\DoctrinePaginator as DoctrineAdapter;
+use Doctrine\ORM\Tools\Pagination\Paginator as ORMPaginator;
+use Zend\Paginator\Paginator;
+
+class IndexController extends AbstractActionController {
+
+    private $_config;
+    private $_pluginRepository;
+    private $_paginator;
+    private $_categoryRepository;
+    private $_nbVersionRepository;
+
+    public function __construct($pluginRepo, $config, PaginatorInterface $paginator, $nbVersionRepository, $categoryRepository, $pvRepo) {
+        $this->_config = $config;
+        $this->_pluginRepository = $pluginRepo;
+        $this->_paginator = $paginator;
+        $this->_nbVersionRepository = $nbVersionRepository;
+        $this->_categoryRepository = $categoryRepository;
+        $this->_pluginVersionRepository = $pvRepo;
+    }
+
+    public function indexAction() {   
+
+        $pageLimit = 10;
+
+        $page = $this->params()->fromQuery('page') ? $this->params()->fromQuery('page') : 1;
+        $cat = $this->params()->fromQuery('cat');
+        $nbv = $this->params()->fromQuery('nbv');
+        $qb = $this->_pluginRepository->getPublicPluginsByNameQB($this->params()->fromQuery('search'), $cat, $nbv);
+        $adapter = new DoctrineAdapter(new ORMPaginator($qb->getQuery(), true));        
+        $paginator = new Paginator($adapter);
+        $paginator->setDefaultItemCountPerPage($pageLimit);        
+        $paginator->setCurrentPageNumber($page);
+
+        return new ViewModel([
+            'paginator' => $paginator,
+            'search' => $this->params()->fromQuery('search'),
+            'categories' => $this->_categoryRepository->getAllCategoriesSortByName(),
+            'versions' => $this->_nbVersionRepository->findAll(),
+            'best' => $this->_pluginRepository->getTopNDownloadedPublic(5),
+            'latest' => $this->_pluginRepository->getLatestNPublic(5),
+        ]);
+    }
+    
+    public function catalogueAction() {
+        $pId = $this->params()->fromQuery('id');
+        if (!empty($pId)) {
+            $plugin = $this->_pluginRepository->getPublicPluginById($pId);                    
+        };   
+
+        return new ViewModel([
+            'plugin' => $plugin
+        ]);
+    }
+
+    public function downloadAction() {
+        $pId = $this->params()->fromQuery('id');
+        if (!empty($pId)) {
+            $pluginVersion = $this->_pluginVersionRepository->find($pId);                    
+        };   
+        if ($pluginVersion->getPlugin()->isPublic()) {
+            $plugin = $pluginVersion->getPlugin();
+            $plugin->incrementDownloadCounter();
+            $this->_pluginRepository->persist($plugin);
+            return  $this->redirect()->toUrl($pluginVersion->getUrl());
+            die($pluginVersion->getUrl());
+        } else {
+            die('No plugin found.');
+        }
+       
+    }
+}
diff --git a/pp3/module/Application/src/Application/Controller/LoginController.php b/pp3/module/Application/src/Application/Controller/LoginController.php
new file mode 100644
index 0000000..dc0cc38
--- /dev/null
+++ b/pp3/module/Application/src/Application/Controller/LoginController.php
@@ -0,0 +1,63 @@
+<?php
+
+
+namespace Application\Controller;
+
+use Zend\Mvc\Controller\AbstractActionController;
+use Zend\View\Model\ViewModel;
+use Zend\Session\Container;
+
+class LoginController extends AbstractActionController {
+
+    private $_config;
+    private $_session;
+    private $_verifierRepository;
+
+    public function __construct($config, $verifierRepository) {
+        $this->_config = $config;
+        $this->_session = new Container();
+        $this->_verifierRepository = $verifierRepository;
+    }
+    
+    public function onGoogleSignInAjaxAction() {
+        $response = $this->getResponse();
+        // user info passed from Google auth
+        $req = $this->request;        
+        if($_SESSION['sessionUserId']) {
+            $response->setContent('');
+        } else {
+            if ($req->isPost()) {
+                $name = $this->params()->fromPost('name');
+                $email= $this->params()->fromPost('email');
+                $_SESSION['sessionUserId'] = $email;
+                $_SESSION['sessionUserEmail'] = $email;        
+                $this->checkVerifier($email);
+                $this->checkAdmin($email);
+                $response->setContent('reload');
+            }
+        }
+       return $response;
+    }
+
+    public function onGoogleSignOutAjaxAction() {
+        $_SESSION['sessionUserId'] = null;
+        $_SESSION['sessionUserEmail'] = null;
+        $_SESSION['isVerifier'] = null;
+        $_SESSION['isAdmin'] = null;
+        die();
+    }
+
+    private function checkVerifier($userId) {
+        if (!empty($userId)) {
+            $verifier = $this->_verifierRepository->findOneBy('user_id', $userId);
+            if ($verifier) {
+                $_SESSION['isVerifier'] = true;
+            }
+        }
+    }
+
+    private function checkAdmin($userId) {
+        $admins = $this->_config['pp3']['admin'];
+        $_SESSION['isAdmin'] = in_array($userId, $admins);
+    }
+}
diff --git a/pp3/module/Application/src/Application/Controller/PluginController.php b/pp3/module/Application/src/Application/Controller/PluginController.php
new file mode 100644
index 0000000..80d3d1e
--- /dev/null
+++ b/pp3/module/Application/src/Application/Controller/PluginController.php
@@ -0,0 +1,351 @@
+<?php
+
+namespace Application\Controller;
+
+use Application\Controller\BaseController;
+use Zend\View\Model\ViewModel;
+use Zend\Session\Container;
+use Application\Pp\MavenDataLoader;
+use Application\Entity\Plugin;
+use Application\Entity\PluginVersion;
+use Zend\Mail;
+use HTMLPurifier;
+use HTMLPurifier_Config;
+
+define('PLUGIN_SESSION_NAMESPACE', 'pp3_plugin_session');
+
+class PluginController extends BaseController {
+
+    private $_pluginRepository;
+    private $_pluginVersionRepository;
+    private $_categoryRepository;
+    private $_verifierRepository;
+
+    public function __construct($pluginRepo, $pvRepo, $categRepository, $config, $verifierRepository) {
+        parent::__construct($config);
+        $this->_pluginRepository = $pluginRepo;
+        $this->_pluginVersionRepository = $pvRepo;
+        $this->_categoryRepository = $categRepository;       
+        $this->_verifierRepository = $verifierRepository;
+    }
+
+    public function syncAction() {
+        $pId = $this->params()->fromQuery('id');
+        $plugin = $this->_pluginRepository->find($pId);        
+        $plugin->setDataLoader(new MavenDataLoader());
+        if (!$plugin->isOwnedBy($this->_sessionUserId)) {
+            return $this->redirect()->toRoute('plugin', array(
+                'action' => 'list'
+            ));
+        }
+        try {
+            $plugin->reloadData();
+            $this->_pluginRepository->persist($plugin);            
+            $this->flashMessenger()->setNamespace('success')->addMessage('Plugin data reloaded from maven-metadata.xml file.');            
+        } catch (\Exception $e) {
+            // maven-metadata.xml not found
+            $this->flashMessenger()->setNamespace('error')->addMessage('Sorry, maven-metadata.xml file is missing.');                
+        }
+        return $this->redirect()->toRoute('plugin', array(
+            'action' => 'list'
+        ));        
+    }
+
+    private function handleImgUpload($imgFolder) {
+        $tmp_name = $_FILES["image-file"]["tmp_name"];
+        // basename() may prevent filesystem traversal attacks;
+        // further validation/sanitation of the filename may be appropriate
+        $name = basename($_FILES["image-file"]["name"]);
+        if(!file_exists($imgFolder)) {
+            mkdir($imgFolder, 0777, true);
+        }
+        if(move_uploaded_file($tmp_name, $imgFolder.'/'.$name)) {
+            return $name; 
+        }        
+    }
+
+    public function indexAction() {
+        $req = $this->request;
+        $plugin = new Plugin();
+        if ($req->isPost()) {
+            $config = HTMLPurifier_Config::createDefault();
+            $purifier = new HTMLPurifier($config);
+            $groupId = $purifier->purify($this->params()->fromPost('groupid'));
+            $artifactId = $purifier->purify($this->params()->fromPost('artifactid'));
+            
+            if (!empty($groupId) && !empty($artifactId)) {
+                $url = $this->_config['pp3']['mavenRepoUrl'].str_replace('.','/', $groupId).'/'.$artifactId.'/maven-metadata.xml';
+                $plugin->setUrl($url);
+                $plugin->setArtifactId($artifactId);
+                $plugin->setGroupId($groupId);
+                $plugin->setStatus(Plugin::STATUS_PRIVATE);
+                $plugin->setAuthor($this->_sessionUserId);
+                $plugin->setDataLoader(new MavenDataLoader());
+                try {
+                    if ($plugin->loadData()) {
+                        $existingPlugins = $this->_pluginRepository->getPluginsByArtifact($plugin->getArtifactId(), $plugin->getGroupId());
+                        if (count($existingPlugins) == 0) {
+                            // ok, proceed to confirmation
+                            $session = new Container(PLUGIN_SESSION_NAMESPACE);
+                            $session->plugin_registered = $plugin;
+                            return $this->redirect()->toRoute('plugin', array(
+                                'action' => 'confirm'
+                            ));
+                        } else {
+                            $this->flashMessenger()->setNamespace('error')->addMessage('Same plugin already registered.');
+                        }
+                    } else {
+                        // empty data from maven-metadata.xml
+                        $this->flashMessenger()->setNamespace('error')->addMessage('maven-metadata.xml file is missing data.');
+                    }
+                } catch (\Exception $e) {
+                    // maven-metadata.xml not found
+                    $this->flashMessenger()->setNamespace('error')->addMessage($e->getMessage());                
+                }
+            } else {
+                $this->flashMessenger()->setNamespace('error')->addMessage('Missing groupId or atrifactId');                
+            }
+        }
+        return new ViewModel([
+            'plugin' => $plugin
+        ]);
+    }
+
+    public function confirmAction() {
+        $session = new Container(PLUGIN_SESSION_NAMESPACE);
+        $plugin = $session->plugin_registered; 
+        if (!$plugin) {            
+            return $this->redirect()->toRoute('plugin', array(
+                'action' => 'index'
+            ));
+        }
+        $req = $this->request;
+        if ($req->isPost()) {
+            $validatedData = $this->_validateAndCleanPluginData(
+                $this->params()->fromPost('author'),
+                $this->params()->fromPost('name'),
+                $this->params()->fromPost('license'),
+                $this->params()->fromPost('description'),
+                $this->params()->fromPost('short_description'),
+                $this->params()->fromPost('category'),
+                $this->params()->fromPost('homepage')
+            );
+            if ($validatedData) {
+                $plugin->setAuthor($validatedData['author']);
+                $plugin->setName($validatedData['name']);
+                $plugin->setLicense($validatedData['license']);
+                $plugin->setDescription($validatedData['description']);
+                $plugin->setShortDescription($validatedData['short_description']);
+                $plugin->setHomepage($validatedData['homepage']);
+                $plugin->setAddedAt(new \DateTime('now'));
+                $plugin->setLastUpdatedAt(new \DateTime('now'));
+                // save also versions
+                if (!empty($plugin->tmpVersions)) {
+                    foreach($plugin->tmpVersions as $vers) {
+                        try {
+                            $v = new PluginVersion();
+                            $v->setVersion($vers);
+                            $v->setPlugin($plugin);
+                            $v->setupUrl();
+                            $plugin->addVersion($v);
+                        } catch (\Exception $e) {
+                            $this->flashMessenger()->setNamespace('error')->addMessage($e->getMessage());                
+                        }
+                    }
+                }
+                // save image
+                $im = $this->handleImgUpload($this->_config['pp3']['catalogSavepath'].'/plugins/'.$plugin->getId());
+                if ($im) {                    
+                    $plugin->setImage($im);
+                }
+
+                // categ
+                $plugin->removeCategories();
+                $this->_pluginRepository->persist($plugin);
+                $cat = $this->_categoryRepository->find($validatedData['category']);
+                if ($cat) {
+                    $plugin->addCategory($cat);
+                }
+                $cat2 = $this->params()->fromPost('category2');
+                if ($cat2 && (!$cat || ($cat2 != $cat->getId()))) {
+                    $cat2 = $this->_categoryRepository->find($this->params()->fromPost('category2'));
+                    if ($cat2) {
+                        //die(var_dump($cat2, $plugin->getCategories()[1], $validatedData['category']));
+                        $plugin->addCategory($cat2);
+                    }
+                }
+
+                $this->_pluginRepository->persist($plugin);
+                $this->flashMessenger()->setNamespace('success')->addMessage('Plugin registered.');
+                $session->getManager()->getStorage()->clear(PLUGIN_SESSION_NAMESPACE);
+
+                // send mail to admins asking for approval
+                $this->_sendApprovalEmail($plugin);
+
+                return $this->redirect()->toRoute('plugin', array(
+                    'action' => 'list'
+                ));
+            } else {
+                $this->flashMessenger()->setNamespace('error')->addMessage('Missing required data.');
+            }            
+        }
+        return new ViewModel([
+            'plugin' => $plugin,
+            'categories' => $this->_categoryRepository->getAllCategoriesSortByName(),
+        ]);
+    }
+
+    public function listAction() {
+        $plugins = $this->_pluginRepository->getPluginsByAuthor($this->_sessionUserId);
+        return new ViewModel(array(
+            'plugins' => $plugins,
+        ));
+    }
+
+    public function editAction() {
+        $pId = $this->params()->fromQuery('id');
+        $plugin = $this->_pluginRepository->find($pId);        
+        if (!$plugin || empty($pId) || !$plugin->isOwnedBy($this->_sessionUserId)) {
+            return $this->redirect()->toRoute('plugin', array(
+                'action' => 'list'
+            ));
+        }
+        $req = $this->request;
+        if ($req->isPost()) {
+            $validatedData = $this->_validateAndCleanPluginData(
+                $this->params()->fromPost('author'),
+                $this->params()->fromPost('name'),
+                $this->params()->fromPost('license'),
+                $this->params()->fromPost('description'),
+                $this->params()->fromPost('short_description'),
+                $this->params()->fromPost('category'),
+                $this->params()->fromPost('homepage')
+            );
+            if ($validatedData) {
+                $plugin->setAuthor($validatedData['author']);
+                $plugin->setName($validatedData['name']);
+                $plugin->setLicense($validatedData['license']);
+                $plugin->setDescription($validatedData['description']);
+                $plugin->setShortDescription($validatedData['short_description']);
+                $plugin->setHomepage($validatedData['homepage']);
+                $plugin->setLastUpdatedAt(new \DateTime('now'));                
+                
+                // save image
+                $im = $this->handleImgUpload($this->_config['pp3']['catalogSavepath'].'/plugins/'.$plugin->getId());
+                if ($im) {                    
+                    $plugin->setImage($im);
+                }
+
+                // categ
+                $plugin->removeCategories();
+                $this->_pluginRepository->persist($plugin);
+                $cat = $this->_categoryRepository->find($validatedData['category']);
+                if ($cat) {
+                    $plugin->addCategory($cat);
+                }
+                $cat2 = $this->params()->fromPost('category2');
+                if ($cat2 && (!$cat || ($cat2 != $cat->getId()))) {
+                    $cat2 = $this->_categoryRepository->find($this->params()->fromPost('category2'));
+                    if ($cat2) {
+                        //die(var_dump($cat2, $plugin->getCategories()[1], $validatedData['category']));
+                        $plugin->addCategory($cat2);
+                    }
+                }
+
+                $this->_pluginRepository->persist($plugin);
+
+                $this->flashMessenger()->setNamespace('success')->addMessage('Plugin updated.');               
+            } else {
+                $this->flashMessenger()->setNamespace('error')->addMessage('Missing required data.');
+            }
+            return $this->redirect()->toUrl('./edit?id='.$plugin->getId());      
+        }
+
+        return new ViewModel(array(
+            'plugin' => $plugin,
+            'categories' => $this->_categoryRepository->getAllCategoriesSortByName(),
+        ));
+    }
+
+    public function deleteAction() {
+        $pId = $this->params()->fromQuery('id');
+        $plugin = $this->_pluginRepository->find($pId);    
+        if (!$plugin || empty($pId) || !$plugin->isOwnedBy($this->_sessionUserId)) {
+            return $this->redirect()->toRoute('plugin', array(
+                'action' => 'list'
+            ));
+        };        
+        $this->flashMessenger()->setNamespace('success')->addMessage('Plugin '.$plugin->getName().' deleted.');
+        $this->_pluginRepository->remove($plugin);
+        return $this->redirect()->toRoute('plugin', array(
+            'action' => 'list'
+        ));
+    }
+
+    private function _validateAndCleanPluginData($author, $name, $license, $description, $shortDescription, $category, $homepage) {
+        if (empty($author) || empty($name) || empty($license) || empty($category) || empty($shortDescription)) {
+            return false;
+        }
+        $config = HTMLPurifier_Config::createDefault();
+        $purifier = new HTMLPurifier($config);
+        return  array(
+            'author' => $purifier->purify($author),
+            'name' => $purifier->purify($name),
+            'license' => $purifier->purify($license),
+            'description' => $purifier->purify($description),
+            'short_description' => $purifier->purify($shortDescription),
+            'category' => $category,
+            'homepage' => $purifier->purify($homepage),
+        );
+    }
+
+    private function _sendApprovalEmail($plugin) {
+        $mail = new Mail\Message();
+        $link = $_SERVER["REQUEST_SCHEME"].'://'.$_SERVER["HTTP_HOST"].$this->url()->fromRoute('admin', array('action' => 'approve'));
+        $mail->setBody('Hello administrator,
+somebody published a new Apache NetBeans plugin in the NetBeans Plugin Portal and it is now waiting for approval to become visible for public.
+
+New plugin: '.$plugin->getName().'
+
+It would be great, if you could login to the NetBeans Plugin Portal at your earliest convenience, make sure the plugin can show up in the list of plugins and then approve it.
+
+'.$link.'
+
+Thanks for your help!
+NetBeans development team
+
+P.S.: This is an automatic email. DO NOT REPLY to this email. ');
+
+        $mail->setFrom('webmaster@netbeans.apache.org', 'NetBeans webmaster');
+        $mail->setSubject('NetBeans plugin waiting for approval: '.$plugin->getName());
+        $transport = new Mail\Transport\Sendmail();
+        $i=0;
+        foreach($this->_verifierRepository->findAll() as $verifier) {
+            if ($i == 0) {
+                $mail->addTo($verifier->getUserId());
+                $i++;
+            } else {
+                $mail->addBcc($verifier->getUserId());
+            }
+        }
+        $transport->send($mail);
+    }
+
+
+    public function searchAutocompleteAction() {       
+        $term = $this->params()->fromQuery('term');
+        $a = array();
+        $response = $this->getResponse();
+        if (!empty($term)) {
+            $plugins = $this->_pluginRepository->getPluginsByName($term);
+            if (!empty($plugins)) {
+                foreach ($plugins as $p) {
+                    $a[] = array('label' => $p->getName(), 'value' => $p->getName());
+                }
+                $response->setContent(json_encode($a));
+            }
+        }
+        return $response;
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Controller/PluginVersionController.php b/pp3/module/Application/src/Application/Controller/PluginVersionController.php
new file mode 100644
index 0000000..64410b8
--- /dev/null
+++ b/pp3/module/Application/src/Application/Controller/PluginVersionController.php
@@ -0,0 +1,126 @@
+<?php
+
+namespace Application\Controller;
+
+use Application\Controller\BaseController;
+use Zend\View\Model\ViewModel;
+use Zend\Session\Container;
+use Application\Pp\MavenDataLoader;
+use Application\Entity\Plugin;
+use Application\Entity\PluginVersion;
+use Application\Entity\NbVersionPluginVersion;
+use HTMLPurifier;
+use HTMLPurifier_Config;
+
+define('PLUGIN_SESSION_NAMESPACE', 'pp3_plugin_session');
+
+class PluginVersionController extends BaseController {
+
+    public function __construct($pluginRepo, $pvRepo, $nbvRepo, $nbVersionPluginVersionRepo, $config, $verificationRepo) {
+        parent::__construct($config);
+        $this->_pluginRepository = $pluginRepo;
+        $this->_pluginVersionRepository = $pvRepo;
+        $this->_nbVersionRepository = $nbvRepo;
+        $this->_nbVersionPluginVersionRepository = $nbVersionPluginVersionRepo;
+        $this->_verificationRepository = $verificationRepo;
+    }
+
+    public function editAction() {
+        $pvId = $this->params()->fromQuery('id');
+        $pluginVersion = $this->_pluginVersionRepository->find($pvId);        
+        if (!$pluginVersion || empty($pvId) || !$pluginVersion->getPlugin()->isOwnedBy($this->_sessionUserId)) {
+            return $this->redirect()->toRoute('plugin', array(
+                'action' => 'list'
+            ));
+        }        
+        $req = $this->request;
+        if ($req->isPost()) {
+            $relnotes = $this->params()->fromPost('relnotes');
+            if (!empty($relnotes)) {
+                $config = HTMLPurifier_Config::createDefault();
+                $purifier = new HTMLPurifier($config);
+                $pluginVersion->setRelnotes($purifier->purify($relnotes));
+                $this->_pluginVersionRepository->persist($pluginVersion);
+                $showFlash = true;
+            }
+            // handle nb versions assignmnent
+            $selectedNbVersionIds = $this->params()->fromPost('nbVersion_ids');
+            if (!empty($selectedNbVersionIds)) {
+                $assignedNbVersions = array();
+                foreach($pluginVersion->getNbVersionsPluginVersions() as $nbvPv) {
+                    // remove if deselected
+                    if (!in_array($nbvPv->getNbVersionId(), $selectedNbVersionIds)) {
+                        $this->_nbVersionPluginVersionRepository->remove($nbvPv);
+                        $showFlash = true;
+                    } else {
+                        $assignedNbVersions[] = $nbvPv->getNbVersionId();
+                    }
+                }                                
+                // and add newly selected
+                foreach($selectedNbVersionIds as $selectedNbVersionId) {
+                    if (!in_array($selectedNbVersionId, $assignedNbVersions)) {
+                        $newNbvpv = new NbVersionPluginVersion();
+                        $newNbvpv->setNbVersion($this->_nbVersionRepository->find($selectedNbVersionId));
+                        $newNbvpv->setPluginVersion($pluginVersion);
+                        $pluginVersion->addNbVersion($newNbvpv);
+                        $showFlash = true;
+                    }
+                }
+                $this->_pluginVersionRepository->persist($pluginVersion);
+            } else {
+                // remove all
+                foreach($pluginVersion->getNbVersionsPluginVersions() as $nbvPv) {                
+                    $this->_nbVersionPluginVersionRepository->remove($nbvPv);
+                    $showFlash = true;
+                }
+            }
+            
+            if ($showFlash) {
+                $this->flashMessenger()->setNamespace('success')->addMessage('Plugin version updated');
+                return $this->redirect()->toUrl('./edit?id='.$pluginVersion->getId());                
+            }
+        }
+        
+        // droping verification
+        $verificationId = $this->params()->fromQuery('verifId');
+        if ($verificationId) {
+            $verification = $this->_verificationRepository->find($verificationId);
+            if ($verification && $verification->getNbVersionPluginVersion()->getPluginVersion()->getId() == $pluginVersion->getId()) {
+                $this->_verificationRepository->remove($verification);
+                $nbvPv = $verification->getNbVersionPluginVersion();
+                $nbvPv->setVerification(null);
+                $this->_nbVersionPluginVersionRepository->persist($nbvPv);
+                $this->flashMessenger()->setNamespace('success')->addMessage('Verification dropped');
+                return $this->redirect()->toUrl('./edit?id='.$pluginVersion->getId());
+            }
+        }
+        
+        
+        $verifiedNbVersions = $this->_nbVersionRepository->getVerifiedNbVersionIdsForPlugin($pluginVersion->getPlugin()->getId());
+        $verifiedNbVersionIds = array();
+        foreach($verifiedNbVersions as $v) {
+            $verifiedNbVersionIds[]=$v['id'];
+        }
+        
+        return new ViewModel([
+            'pluginVersion' => $pluginVersion,
+            'nbVersions' => $this->_nbVersionRepository->findAll(),
+            'verifiedNbVersionIds' => $verifiedNbVersionIds,
+        ]);
+    }
+
+    public function deleteAction() {
+        $pId = $this->params()->fromQuery('id');
+        $pluginVersion = $this->_pluginVersionRepository->find($pId);        
+        if (!$pluginVersion || empty($pId) || !$pluginVersion->getPlugin()->isOwnedBy($this->_sessionUserId)) {
+            return $this->redirect()->toRoute('plugin', array(
+                'action' => 'list'
+            ));
+        };        
+        $this->flashMessenger()->setNamespace('success')->addMessage('Plugin version '.$pluginVersion->getVersion().' deleted');
+        $this->_pluginVersionRepository->remove($pluginVersion);
+        return $this->redirect()->toRoute('plugin', array(
+            'action' => 'list'
+        ));
+    }
+}
diff --git a/pp3/module/Application/src/Application/Controller/VerificationController.php b/pp3/module/Application/src/Application/Controller/VerificationController.php
new file mode 100644
index 0000000..0b37463
--- /dev/null
+++ b/pp3/module/Application/src/Application/Controller/VerificationController.php
@@ -0,0 +1,238 @@
+<?php
+
+namespace Application\Controller;
+
+use Application\Controller\BaseController;
+use Zend\View\Model\ViewModel;
+use Application\Entity\Verification;
+use Application\Pp\Catalog;
+use Zend\Session\Container;
+use Zend\Mail;
+use HTMLPurifier;
+use HTMLPurifier_Config;
+
+class VerificationController extends BaseController {
+
+    private $_nbVersionPluginVersionRepository;
+    private $_verificationRepository;
+    private $_verifierRepository;
+    private $_verificationRequestRepository;
+    private $_pluginVersionRepository;
+
+    public function __construct($nbVersionPluginVersionRepo, $verificationRepo, 
+                                $verifierRepository, $verificationRequestRepository, $config,
+                                $pluginVersionRepository) {
+        parent::__construct($config);
+        $this->_nbVersionPluginVersionRepository = $nbVersionPluginVersionRepo;
+        $this->_verificationRepository = $verificationRepo;
+        $this->_verifierRepository = $verifierRepository;
+        $this->_verificationRequestRepository = $verificationRequestRepository;
+        $this->_pluginVersionRepository = $pluginVersionRepository;
+
+        $session = new Container();
+        $this->_sessionUserId = $session->userId ? $session->userId : ANONUSER;
+    } 
+
+    public function listAction() {
+        return new ViewModel([
+            'verificationRequests' => $this->_verificationRequestRepository->getVerificationRequestsForVerifier($this->_sessionUserId),
+            'isAdmin' => $this->_isAdmin,
+        ]);
+    }
+
+    public function voteGoAction() {
+        $this->_handleVote(\Application\Entity\VerificationRequest::VOTE_GO);
+    }
+
+    public function voteNoGoAction() {
+        $this->_handleVote(\Application\Entity\VerificationRequest::VOTE_NOGO);
+    }
+
+    public function voteUndecidedAction() {
+        $this->_handleVote(\Application\Entity\VerificationRequest::VOTE_UNDECIDED);
+    }
+
+    private function _handleVote($vote) {
+        $reqId = $this->params()->fromQuery('id');
+        $bailOut = false;
+        if (empty($reqId)) {
+            $bailOut = true;
+        }
+        $req = $this->_verificationRequestRepository->find($reqId);
+        if (!$req || $req->getVerifier()->getUserId() !== $this->_sessionUserId) {
+            $bailOut = true;
+        }
+        if ($bailOut) {
+            return $this->redirect()->toRoute('verification', array(
+                'action' => 'list'
+            ));
+        }
+        $req->setVote($vote);
+        $req->setVotedAt(new \DateTime('now'));
+        $comment = $this->params()->fromPost('comment');
+        if (!empty($comment)) {
+            $config = HTMLPurifier_Config::createDefault();
+            $purifier = new HTMLPurifier($config);
+            $comment = $purifier->purify($comment);
+            $req->setComment($comment);
+        }
+        $this->_verificationRequestRepository->persist($req);
+        $votesBreakdown = $this->_verificationRequestRepository->getVotesBreakdownForVerification($req->getVerification()->getid());
+        $verification = $req->getVerification();
+        $verification->resolveStatus($votesBreakdown);
+        $this->_verificationRepository->persist($verification);
+        if ($verification->getStatus() == \Application\Entity\Verification::STATUS_NOGO) {
+            $this->_sendNoGoNotification($req->getVerification(), $comment);
+        } elseif ($verification->getStatus() == \Application\Entity\Verification::STATUS_GO) {
+            $version = $verification->getNbVersionPluginVersion()->getNbVersion()->getVersion();
+            $items = $this->_pluginVersionRepository->getVerifiedVersionsByNbVersion($version);
+            $link = $_SERVER["REQUEST_SCHEME"].'://'.$_SERVER["HTTP_HOST"].$this->url()->fromRoute('catalogue', array('action' => 'download')).'?id=';
+            $catalog = new Catalog($version, $items, false, $this->_config['pp3']['dtdPath'], $link);            
+            try {
+                $xml = $catalog->asXml(true);
+                $catalog->storeXml($this->_config['pp3']['catalogSavepath'], $xml);
+            } catch (\Exception $e){
+                $this->flashMessenger()->setNamespace('error')->addMessage($e->getMessage());                        
+            }    
+            $this->_sendGoNotification($req->getVerification(), $comment);
+        }
+        $this->flashMessenger()->setNamespace('success')->addMessage('Vote cast');
+        return $this->redirect()->toRoute('verification', array(
+            'action' => 'list'
+        ));
+    }
+
+    public function voteMasterGoAction() {
+        $this->_handleMasterVote(\Application\Entity\Verification::STATUS_GO);
+    }
+
+    public function voteMasterNoGoAction() {
+        $this->_handleMasterVote(\Application\Entity\Verification::STATUS_NOGO);
+    }
+
+    private function _handleMasterVote($vote) {
+        $verId = $this->params()->fromQuery('id');
+        $bailOut = false;
+        if (empty($verId) || !$this->_isAdmin) {
+            $bailOut = true;
+        }
+        $ver = $this->_verificationRepository->find($verId);
+        if (!$ver) {
+            $bailOut = true;
+        }
+        if ($bailOut) {
+            return $this->redirect()->toRoute('verification', array(
+                'action' => 'list'
+            ));
+        }
+        $ver->setStatus($vote);
+        $comment = $this->params()->fromPost('comment');
+        if (!empty($comment)) {
+            $config = HTMLPurifier_Config::createDefault();
+            $purifier = new HTMLPurifier($config);
+            $comment = $purifier->purify($comment);
+            $this->_sendNoGoNotification($ver, $comment);
+        }
+        $this->_verificationRepository->persist($ver);
+        // delete related requests 
+        $this->_verificationRequestRepository->deleteRequestsOfVerification($ver->getId());        
+        $this->flashMessenger()->setNamespace('success')->addMessage('Master vote cast');
+        return $this->redirect()->toRoute('verification', array(
+            'action' => 'list'
+        ));
+    }
+
+    public function createAction() {
+        $bailOut = false;
+        $nbvPvId = $this->params()->fromQuery('nbvPvId');
+        if (empty($nbvPvId)) {
+            $bailOut = true;
+        }
+        $nbVersionPluginVersion = $this->_nbVersionPluginVersionRepository->find($nbvPvId);
+        if (!$nbVersionPluginVersion) {
+            $bailOut = true;
+        }
+        $plugin = $nbVersionPluginVersion->getPluginVersion()->getPlugin();
+        if (!$plugin->isOwnedBy($this->_sessionUserId)) {
+            $bailOut = true;
+        }
+        if ($bailOut) {
+            return $this->redirect()->toRoute('plugin', array(
+                'action' => 'list'
+            ));
+        }
+        // create verification
+        $verification = new Verification();
+        $verification->setStatus(Verification::STATUS_REQUESTED);
+        $verification->setCreatedAt(new \DateTime('now'));
+        $this->_verificationRepository->persist($verification);
+        // join it to nbVersionPluginVersion
+        $nbVersionPluginVersion->setVerification($verification);
+        $this->_nbVersionPluginVersionRepository->persist($nbVersionPluginVersion);
+        // generate requests for all verifiers
+        $verifiers = $this->_verifierRepository->findAll();
+        $verification->createRequests($verifiers, $plugin);
+        $this->_verificationRepository->persist($verification);
+        $this->flashMessenger()->setNamespace('success')->addMessage('Verification Requested.');
+        return $this->redirect()->toUrl('../plugin-version/edit?id='.$nbVersionPluginVersion->getPluginVersion()->getId());         
+    }
+
+    private function _sendNoGoNotification($verification, $comment) {
+        $plugin = $verification->getNbVersionPluginVersion()->getPluginVersion()->getPlugin();
+        $nbVersion = $verification->getNbVersionPluginVersion()->getNbVersion()->getVersion();
+        $pluginVersion = $verification->getNbVersionPluginVersion()->getPluginVersion()->getVersion();
+        $mail = new Mail\Message();
+        $mail->addTo($plugin->getAuthor());
+        $mail->setFrom('webmaster@netbeans.apache.org', 'NetBeans webmaster');
+        $mail->setSubject('Verification of your '.$plugin->getName().' is complete');
+        $mail->setBody('Hello plugin owner,
+
+this is to inform you that publishing of your plugin on the Plugin Portal Update Center was NOT approved. Please read comments from plugin verifiers below, if any.
+
+Plugin: '.$plugin->getName().'
+NetBeans version: '.$nbVersion.'
+Verification status: NOGO
+Comments: '.$comment.'
+
+If your plugin was verified successfully, it should be already available on the Plugin Portal Update Center by now:
+
+http://netbeans-vm.apache.org/pluginportal/data/'.$nbVersion.'/catalog.xml.gz
+
+Thanks for your contribution!
+NetBeans development team
+
+P.S.: This is an automatic email. DO NOT REPLY to this email.');
+        $transport = new Mail\Transport\Sendmail();
+        $transport->send($mail);
+        // die(var_dump($mail->getBody()));
+    }
+
+    private function _sendGoNotification($verification, $comment) {
+        $plugin = $verification->getNbVersionPluginVersion()->getPluginVersion()->getPlugin();
+        $nbVersion = $verification->getNbVersionPluginVersion()->getNbVersion()->getVersion();
+        $pluginVersion = $verification->getNbVersionPluginVersion()->getPluginVersion()->getVersion();
+        $mail = new Mail\Message();
+        $mail->addTo($plugin->getAuthor());
+        $mail->setFrom('webmaster@netbeans.apache.org', 'NetBeans webmaster');
+        $mail->setSubject('Verification of your '.$plugin->getName().' is complete');
+        $mail->setBody('Hello plugin owner,
+
+this is to inform you that publishing of your plugin on the Plugin Portal Update Center was approved.
+
+Plugin: '.$plugin->getName().'
+NetBeans version: '.$nbVersion.'
+Verification status: GO
+
+Your plugin should be already available on the Plugin Portal Update Center by now:
+
+http://netbeans-vm.apache.org/pluginportal/data/'.$nbVersion.'/catalog.xml.gz
+
+Thanks for your contribution!
+NetBeans development team
+
+P.S.: This is an automatic email. DO NOT REPLY to this email.');
+        $transport = new Mail\Transport\Sendmail();
+        $transport->send($mail);
+        // die(var_dump($mail->getBody()));
+    }
+}
\ No newline at end of file
diff --git a/pp3/module/Application/src/Application/Entity/Base/Category.php b/pp3/module/Application/src/Application/Entity/Base/Category.php
new file mode 100644
index 0000000..731caab
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Base/Category.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Application\Entity\Base;
+
+use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Common\Collections\ArrayCollection;
+
+class Category {
+
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     * @ORM\Column(type="integer")
+     */
+    protected $id;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $name;
+
+    /**
+     * @ORM\ManyToMany(targetEntity="Plugin", mappedBy="categories")
+     */
+    protected $plugins;
+
+    public function __construct() {
+        $this->plugins = new ArrayCollection();
+        return $this;
+    }
+
+    public function getId() {
+        return $this->id;
+    }
+
+    public function setId($id) {
+        $this->id = $id;
+    }
+    
+    public function getName() {
+        return $this->name;
+    }
+    
+    public function setName($name) {
+        $this->name = $name;
+    }
+
+    public function getPlugins() {
+        return $this->plugins;
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Entity/Base/NbVersion.php b/pp3/module/Application/src/Application/Entity/Base/NbVersion.php
new file mode 100644
index 0000000..3ab2b87
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Base/NbVersion.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Application\Entity\Base;
+
+use Doctrine\ORM\Mapping as ORM;
+use Application\Entity\NbVersionPluginVersion;
+use Doctrine\Common\Collections\ArrayCollection;
+
+class NbVersion {
+
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     * @ORM\Column(type="integer")
+     */
+    protected $id;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $version;
+
+    /** @ORM\Column(type="integer") */
+    protected $verifiable;
+
+    /**
+     *  @ORM\OneToMany(targetEntity="NbVersionPluginVersion", mappedBy="nbVersion", cascade={"persist", "remove"})     
+     */
+    protected $nbVersionsPluginVersions;
+    
+    public function __construct() {
+        $this->nbVersionsPluginVersions = new ArrayCollection();
+        return $this;
+    }
+
+    public function getId() {
+        return $this->id;
+    }
+    
+    public function setId($id) {
+        $this->id = $id;
+    }
+    
+    public function setVersion($v) {
+        $this->version = $v;
+    }
+
+    public function getVersion() {
+        return $this->version;
+    }
+
+    public function setVerifiable($v) {
+        $this->verifiable = $v;
+    }
+
+    public function getVerifiable() {
+        return $this->verifiable;
+    }
+
+    public function getNbVersionsPluginVersions() {
+        return $this->nbVersionsPluginVersions;
+    }
+}
diff --git a/pp3/module/Application/src/Application/Entity/Base/NbVersionPluginVersion.php b/pp3/module/Application/src/Application/Entity/Base/NbVersionPluginVersion.php
new file mode 100644
index 0000000..1124ce1
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Base/NbVersionPluginVersion.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace Application\Entity\Base;
+
+use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Common\Collections\ArrayCollection;
+
+class NbVersionPluginVersion {
+
+     /**
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     * @ORM\Column(type="integer")
+     */
+    protected $id;
+
+    /** @ORM\Column(type="integer") */
+    protected $plugin_version_id;
+
+    /** @ORM\Column(type="integer") */
+    protected $nb_version_id;
+
+    /** @ORM\Column(type="integer") */
+    protected $verification_id;
+
+    /**
+     * @ORM\ManyToOne(targetEntity="PluginVersion", inversedBy="nbVersionsPluginVersions")
+     * @ORM\JoinColumn(name="plugin_version_id", referencedColumnName="id")
+     */
+    protected $pluginVersion;
+
+    /**
+     * @ORM\ManyToOne(targetEntity="NbVersion", inversedBy="nbVersionsPluginVersions")
+     * @ORM\JoinColumn(name="nb_version_id", referencedColumnName="id")
+     */
+    protected $nbVersion;
+
+    /**
+     * @ORM\OneToOne(targetEntity="Verification", inversedBy="nbVersionPluginVersion", cascade={"remove"})
+     * @ORM\JoinColumn(name="verification_id", referencedColumnName="id")
+     */
+    protected $verification;
+
+    public function __construct() {
+        $this->pluginVersion = new ArrayCollection();
+        return $this;
+    }
+
+    public function getNbVersionId() {
+        return $this->nb_version_id;
+    }
+
+    public function setNbVersionId($id) {
+        $this->nb_version_id = $id;
+    }
+
+    public function getId() {
+        return $this->id;
+    }
+
+    public function setId($id) {
+        $this->id = $id;
+    }
+
+
+    public function getPluginVersion() {
+        return $this->pluginVersion;
+    }
+
+    public function setPluginVersion($pluginVersion) {
+        $this->pluginVersion = $pluginVersion;
+    }    
+
+    public function getNbVersion() {
+        return $this->nbVersion;
+    }
+
+    public function setNbVersion($nbVersion) {
+        $this->nbVersion = $nbVersion;
+    }   
+    
+    public function getVerificationId() {
+        return $this->verification_id;
+    }
+
+    public function getVerification() {
+        return $this->verification;
+    }
+
+    public function setVerification($v) {
+        $this->verification = $v;
+    }
+}
\ No newline at end of file
diff --git a/pp3/module/Application/src/Application/Entity/Base/Plugin.php b/pp3/module/Application/src/Application/Entity/Base/Plugin.php
new file mode 100644
index 0000000..30b7f3b
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Base/Plugin.php
@@ -0,0 +1,240 @@
+<?php
+
+namespace Application\Entity\Base;
+
+use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Common\Collections\ArrayCollection;
+
+class Plugin {
+
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     * @ORM\Column(type="integer")
+     */
+    protected $id;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $name;
+    
+    /** @ORM\Column(type="string", length=255) */
+    protected $artifactid;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $groupid;
+
+    /** @ORM\Column(type="text") */
+    protected $description;
+    
+    /** @ORM\Column(type="text") */
+    protected $short_description;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $license;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $author;
+
+    /** @ORM\Column(type="datetime") */
+    protected $added_at;
+
+    /** @ORM\Column(type="datetime") */
+    protected $last_updated_at;
+
+    /** @ORM\Column(type="datetime") */
+    protected $approved_at;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $url;
+
+    /** @ORM\Column(type="integer") */
+    protected $status;
+    
+    /** @ORM\Column(type="string", length=255) */
+    protected $latest_version;
+    
+    /** @ORM\Column(type="string", length=255) */
+    protected $release_version;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $image;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $homepage;
+
+    /** @ORM\Column(type="integer") */
+    protected $downloads;
+    
+    /**
+     * @ORM\OneToMany(targetEntity="PluginVersion", mappedBy="plugin", cascade={"persist", "remove"})
+     */
+    protected $versions;
+    
+    /** 
+    * @ORM\ManyToMany(targetEntity="Category", inversedBy="plugins")
+    * @ORM\JoinTable(name="plugin_category")
+    */
+    protected $categories;
+
+    public function __construct() {
+        $this->versions = new ArrayCollection();
+        $this->categories = new ArrayCollection();
+        return $this;
+    }
+
+    public function getLatestVersion() {
+        return $this->latest_version;
+    }
+    
+    public function setLatestVersion($ltv) {
+        $this->latest_version = $ltv;
+    }
+
+    public function getReleaseVersion() {
+        return $this->release_version;
+    }
+    
+    public function setReleaseVersion($rv) {
+        $this->release_version = $rv;
+    }
+
+    public function getId() {
+        return $this->id;
+    }
+
+    public function setId($id) {
+        $this->id = $id;
+    }
+
+    public function getName() {
+        return $this->name;
+    }
+
+    public function setName($name) {
+        $this->name = $name;
+    }
+
+    public function getDescription() {
+        return $this->description;
+    }
+
+    public function setDescription($description) {
+        $this->description = $description;
+    }
+    
+    public function getShortDescription() {
+        return $this->short_description;
+    }
+
+    public function setShortDescription($description) {
+        $this->short_description = $description;
+    }
+
+    public function getLicense() {
+        return $this->license;
+    }
+
+    public function setLicense($license) {
+        $this->license = $license;
+    }
+
+    public function getAuthor() {
+        return $this->author;
+    }
+
+    public function setAuthor($author) {
+        $this->author = $author;
+    }
+
+    public function getAddedAt() {
+        return $this->added_at;
+    }
+
+    public function setAddedAt($added_at) {
+        $this->added_at = $added_at;
+    }
+
+    public function getLastUpdatedAt() {
+        return $this->last_updated_at;
+    }
+
+    public function setLastUpdatedAt($lupat) {
+        $this->last_updated_at = $lupat;
+    }
+    
+    public function getUrl() {
+        return $this->url;
+    }
+
+    public function setUrl($url) {
+        $this->url = $url;
+    }
+
+    public function getStatus() {
+        return $this->status;
+    }
+
+    public function setStatus($status) {
+        $this->status = $status;
+    }
+    
+    public function getArtifactId() {
+        return $this->artifactid;
+    }
+    
+    public function setArtifactId($aid) {
+        $this->artifactid = $aid;
+    }
+
+    public function getGroupId() {
+        return $this->groupid;
+    }
+    
+    public function setGroupId($gid) {
+        $this->groupid = $gid;
+    }
+
+    public function getVersions() {
+        return $this->versions;
+    }
+
+    public function getCategories() {
+        return $this->categories;
+    }
+
+    public function setImage($im) {
+        $this->image = $im;
+    }
+
+    public function getImage() {
+        return $this->image;
+    }
+
+    public function getHomepage() {
+        return $this->homepage;
+    }
+
+    public function setHomepage($hp) {
+        if (!empty($hp) && !preg_match('/^http:\/\/|^https:\/\//i', $hp)) {
+            $hp = 'http://'.$hp;
+        }
+        $this->homepage = $hp;
+    }
+
+    public function getDownloads() {
+        return $this->downloads;
+    }
+
+    public function setDownloads($dl) {
+        $this->downloads = $dl;
+    }
+
+    public function getApprovedAt() {
+        return $this->approved_at;
+    }
+
+    public function setApprovedAt($approved_at) {
+        $this->approved_at = $approved_at;
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Entity/Base/PluginVersion.php b/pp3/module/Application/src/Application/Entity/Base/PluginVersion.php
new file mode 100644
index 0000000..ae0e82c
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Base/PluginVersion.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace Application\Entity\Base;
+
+use Doctrine\ORM\Mapping as ORM;
+use Application\Entity\Plugin;
+use Application\Entity\NbVersionPluginVersion;
+use Doctrine\Common\Collections\ArrayCollection;
+
+class PluginVersion {
+
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     * @ORM\Column(type="integer")
+     */
+    protected $id;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $version;
+    
+    /** @ORM\Column(type="string", length=255) */
+    protected $url;
+    
+    /** @ORM\Column(type="text") */
+    protected $relnotes;
+    
+    /** @ORM\Column(type="integer") */
+    protected $plugin_id;
+
+    /**
+     *  @ORM\OneToMany(targetEntity="NbVersionPluginVersion", mappedBy="pluginVersion", cascade={"persist", "remove"})     
+     */
+    protected $nbVersionsPluginVersions;
+    
+    /**
+     * @ORM\ManyToOne(targetEntity="Plugin", inversedBy="versions")
+     * @ORM\JoinColumn(name="plugin_id", referencedColumnName="id")
+     */
+    protected $plugin;
+
+    public function __construct() {
+        $this->nbVersionsPluginVersions = new ArrayCollection();
+        return $this;
+    }
+
+    public function getId() {
+        return $this->id;
+    }
+    
+    public function setId($id) {
+        $this->id = $id;
+    }
+    
+    public function setVersion($v) {
+        $this->version = $v;
+    }
+
+    public function getVersion() {
+        return $this->version;
+    }
+    
+    public function getUrl() {
+        return $this->url;
+    }
+
+    public function setUrl($url) {
+        $this->url = $url;
+    }
+    
+    public function getRelnotes() {
+        return $this->relnotes;
+    }
+
+    public function setRelnotes($relnotes) {
+        $this->relnotes = $relnotes;
+    }
+    
+    public function getPluginId() {
+        return $this->plugin_id;
+    }
+
+    public function setPluginId($pluginId) {
+        $this->plugin_id = $pluginId;
+    }
+    
+    public function getPlugin() {
+        return $this->plugin;
+    }
+
+    public function setPlugin($plugin) {
+        $this->plugin = $plugin;
+    }
+    
+    public function getNbVersionsPluginVersions() {
+        return $this->nbVersionsPluginVersions;
+    }
+}
diff --git a/pp3/module/Application/src/Application/Entity/Base/Verification.php b/pp3/module/Application/src/Application/Entity/Base/Verification.php
new file mode 100644
index 0000000..df8d157
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Base/Verification.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Application\Entity\Base;
+
+use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Common\Collections\ArrayCollection;
+
+class Verification {
+
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     * @ORM\Column(type="integer")
+     */
+    protected $id;
+
+    /** @ORM\Column(type="integer") */
+    protected $status;
+
+    /** @ORM\Column(type="datetime") */
+    protected $created_at;
+
+    /** @ORM\Column(type="integer") */
+    protected $plugin_version_id;
+
+    /**
+     * @ORM\OneToMany(targetEntity="VerificationRequest", mappedBy="verification", cascade={"persist", "remove"})
+     */
+    protected $verification_requests;
+
+    /**
+     * @ORM\OneToOne(targetEntity="NbVersionPluginVersion", mappedBy="verification")
+     */
+    protected $nbVersionPluginVersion;
+
+    public function __construct() {
+        $this->verification_requests = new ArrayCollection();
+        return $this;
+    }
+
+    public function getId() {
+        return $this->id;
+    }
+
+    public function setId($id) {
+        $this->id = $id;
+    }
+
+    public function getStatus() {
+        return $this->status;
+    }
+
+    public function setStatus($status) {
+        $this->status = $status;
+    }
+
+    public function getCreatedAt() {
+        return $this->created_at;
+    }
+
+    public function setCreatedAt($cat) {
+        $this->created_at = $cat;
+    }
+
+    public function getPluginVersionId() {
+        return $this->plugin_version_id;
+    }
+
+    public function setPluginVersionId($pvid) {
+        $this->plugin_version_id = $pvid;
+    }
+
+    public function getPluginVersion() {
+        return $this->plugin_version;
+    }      
+    
+    public function getVerificationRequests() {
+        return $this->verification_requests;
+    }
+
+    public function getNbVersionPluginVersion() {
+        return $this->nbVersionPluginVersion;
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Entity/Base/VerificationRequest.php b/pp3/module/Application/src/Application/Entity/Base/VerificationRequest.php
new file mode 100644
index 0000000..9badafa
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Base/VerificationRequest.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace Application\Entity\Base;
+
+use Doctrine\ORM\Mapping as ORM;
+
+class VerificationRequest {
+
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     * @ORM\Column(type="integer")
+     */
+    protected $id;
+
+    /** @ORM\Column(type="datetime") */
+    protected $created_at;
+
+    /** @ORM\Column(type="integer") */
+    protected $vote;
+
+    /** @ORM\Column(type="datetime") */
+    protected $voted_at;
+
+    /** @ORM\Column(type="text") */
+    protected $comment;
+
+    /** @ORM\Column(type="integer") */
+    protected $verification_id;
+
+    /** @ORM\Column(type="integer") */
+    protected $verifier_id;
+    
+    /**
+     * @ORM\ManyToOne(targetEntity="Verification", inversedBy="verification_requests")
+     * @ORM\JoinColumn(name="verification_id", referencedColumnName="id")
+     */
+    protected $verification;
+    
+    /**
+     * @ORM\ManyToOne(targetEntity="Verifier", inversedBy="verification_requests")
+     * @ORM\JoinColumn(name="verifier_id", referencedColumnName="id")
+     */
+    protected $verifier;
+
+    public function __construct() {
+        return $this;
+    }
+
+    public function getId() {
+        return $this->id;
+    }
+
+    public function setId($id) {
+        $this->id = $id;
+    }
+
+    public function getCreatedAt() {
+        return $this->created_at;
+    }
+
+    public function setCreatedAt($cat) {
+        $this->created_at = $cat;
+    }
+
+    public function getVote() {
+        return $this->vote;
+    }
+
+    public function setVote($vote) {
+        $this->vote = $vote;
+    }
+
+    public function getVotedAt() {
+        return $this->voted_at;
+    }
+
+    public function setVotedAt($vat) {
+        $this->voted_at = $vat;
+    }
+
+    public function getComment() {
+        return $this->comment;
+    }
+
+    public function setComment($cmnt) {
+        $this->comment = $cmnt;
+    }
+
+    public function getVerificationId() {
+        return $this->verification_id;
+    }
+
+    public function setVerificationId($vid) {
+        $this->verification_id = $vid;
+    }
+
+    public function getVerifierId() {
+        return $this->verifier_id;
+    }
+
+    public function setVerifierId($vid) {
+        $this->verifier_id = $vid;
+    }
+    
+    public function getVerification() {
+        return $this->verification;
+    }
+
+    public function setVerification($v) {
+        $this->verification = $v;
+    }
+    
+    public function getVerifier() {
+        return $this->verifier;
+    }
+
+    public function setVerifier($v) {
+        $this->verifier = $v;
+    }
+}
diff --git a/pp3/module/Application/src/Application/Entity/Base/Verifier.php b/pp3/module/Application/src/Application/Entity/Base/Verifier.php
new file mode 100644
index 0000000..176e551
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Base/Verifier.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Application\Entity\Base;
+
+use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Common\Collections\ArrayCollection;
+
+class Verifier {
+
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     * @ORM\Column(type="integer")
+     */
+    protected $id;
+
+    /** @ORM\Column(type="string", length=255) */
+    protected $user_id;
+
+    /**
+     * @ORM\OneToMany(targetEntity="VerificationRequest", mappedBy="verifier")
+     */
+    protected $verification_requests;
+
+    public function __construct() {
+        $this->verification_requests = new ArrayCollection();
+        return $this;
+    }
+
+    public function getId() {
+        return $this->id;
+    }
+
+    public function setId($id) {
+        $this->id = $id;
+    }
+    
+    public function getUserId() {
+        return $this->user_id;
+    }
+    
+    public function setUserId($uid) {
+        $this->user_id = $uid;
+    }
+
+    public function getVerificationRequests() {
+        return $this->verification_requests;
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Entity/Category.php b/pp3/module/Application/src/Application/Entity/Category.php
new file mode 100644
index 0000000..cb9eea7
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Category.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Application\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(name="category")
+ */
+class Category extends Base\Category {
+
+}
diff --git a/pp3/module/Application/src/Application/Entity/NbVersion.php b/pp3/module/Application/src/Application/Entity/NbVersion.php
new file mode 100644
index 0000000..003222b
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/NbVersion.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Application\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(name="nb_version")
+ */
+class NbVersion extends Base\NbVersion {
+        
+    const VERIFIABLE_YES = 1;
+    const VERIFIABLE_NO  = 0;
+
+}
diff --git a/pp3/module/Application/src/Application/Entity/NbVersionPluginVersion.php b/pp3/module/Application/src/Application/Entity/NbVersionPluginVersion.php
new file mode 100644
index 0000000..5356e67
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/NbVersionPluginVersion.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Application\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(name="nb_version_plugin_version")
+ */
+class NbVersionPluginVersion extends Base\NbVersionPluginVersion {
+
+}
diff --git a/pp3/module/Application/src/Application/Entity/Plugin.php b/pp3/module/Application/src/Application/Entity/Plugin.php
new file mode 100644
index 0000000..9e24daf
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Plugin.php
@@ -0,0 +1,164 @@
+<?php
+
+namespace Application\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+use Application\Entity\PluginVersion;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(name="plugin")
+ */
+class Plugin extends Base\Plugin {   
+    
+    const STATUS_PRIVATE = 1;
+    const STATUS_PUBLIC = 2;
+
+    private $_dataLoader;
+    public $tmpVersions;
+    
+    public function setDataLoader($dl) {
+        $this->_dataLoader = $dl;
+    }
+    
+    public function reloadData() {
+        $data = $this->_dataLoader->getData($this);
+        if ($this->_validateData($data) && $this->artifactid == $data['artifactId']) {
+            if (!empty($data['versioning'])) {
+                $versioning = $data['versioning'];
+                if (!empty($versioning['latest'])) {
+                    $this->setLatestVersion($versioning['latest']);
+                }
+                if (!empty($versioning['release'])) {
+                    $this->setReleaseVersion($versioning['release']);
+                }
+                if (!empty($versioning['versions']['version'])) {
+                    $incomingVersions = array_flip($versioning['versions']['version']);
+                    // check for new versions only               
+                    foreach ($this->versions as $registeredVersion) {
+                        unset($incomingVersions[$registeredVersion->getVersion()]);
+                    }
+                    $incomingVersions = array_flip($incomingVersions);
+                    foreach ($incomingVersions as $vers) {
+                        $v = new PluginVersion();
+                        $v->setVersion($vers);
+                        $v->setPlugin($this);
+                        $v->setupUrl();
+                        $this->addVersion($v);
+                    }
+                }
+            }
+            return true;
+        }
+    }
+
+    public function loadData() {
+        $data = $this->_dataLoader->getData($this);
+        if ($this->_validateData($data)) {
+            $this->setArtifactId($data['artifactId']);
+            $this->setGroupId($data['groupId']);
+            if (!empty($data['versioning'])) {
+                $versioning = $data['versioning'];
+                if (!empty($versioning['latest'])) {
+                    $this->setLatestVersion($versioning['latest']);
+                }
+                if (!empty($versioning['release'])) {
+                    $this->setReleaseVersion($versioning['release']);
+                    // load additional info from release
+                    $releaseData = $this->_dataLoader->getReleaseData($this);
+                    if(!empty($releaseData['name'])) {
+                        $this->setName($releaseData['name']);
+                    }
+                    if(!empty($releaseData['description'])) {
+                        $desc = preg_replace('/\s\s+/', ' ', trim($releaseData['description']));
+                        $this->setShortDescription($desc);
+                        $this->setDescription($desc);
+                    }
+                    if(!empty($releaseData['url'])) {
+                        $this->setHomepage($releaseData['url']);
+                    }
+                    if(!empty($releaseData['licenses']) && !empty($releaseData['licenses']['license'])) {
+                        $this->setLicense($releaseData['licenses']['license']['name']);
+                    }
+                }
+                if (!empty($versioning['versions'])) {
+                    // handle some issues with serialization of xml into array
+                    if (!is_array($versioning['versions']['version'])) {
+                        $this->tmpVersions = array($versioning['versions']['version']);     
+                    } else {
+                        $this->tmpVersions = $versioning['versions']['version'];                    
+                    }
+                }
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public function addVersion($version) {
+        $this->versions[] = $version;
+    }
+
+    public function addCategory($category) {
+        $this->categories[] = $category;
+    }
+
+    public function removeCategories() {
+        $this->categories = [];
+    }
+
+    private function _validateData($data) {
+        if (
+            empty($data['artifactId']) || empty($data['groupId'])
+        ) {
+            return false;
+        }
+        return true;
+    }
+
+    public function getStatusIconClass() {
+        if ($this->status === self::STATUS_PRIVATE) {
+            return 'fa-eye-slash color-red';
+        } elseif ($this->status === self::STATUS_PUBLIC) {
+            return 'fa-eye color-green';
+        }
+    }
+
+    public function getStatusTitle() {
+        if ($this->status === self::STATUS_PRIVATE) {
+            return 'Waiting for approval';
+        } elseif ($this->status === self::STATUS_PUBLIC) {
+            return 'Approved and published on '.($this->getApprovedAt() ? $this->getApprovedAt()->format('Y-m-d') : 'N/A');
+        }
+    }
+
+    public function getAuthorName() {
+        $split = explode('@', $this->getAuthor());
+        return $split[0];
+    }
+
+    public function incrementDownloadCounter() {
+        $this->downloads++;
+    }
+
+    public function isPublic() {
+        return $this->status === self::STATUS_PUBLIC;
+    }
+
+    public function isOwnedBy($userId) {
+        return $this->author == $userId;
+    }
+
+    public function setUrl($url) {
+        $this->url = $this->sanitizePluginUrl($url);
+    }
+
+    private function sanitizePluginUrl($url) {
+        if (!preg_match('/.*maven-metadata\.xml$/i', $url, $match)) {
+            return trim($url,'/').'/maven-metadata.xml';
+        }
+        return $url;
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Entity/PluginVersion.php b/pp3/module/Application/src/Application/Entity/PluginVersion.php
new file mode 100644
index 0000000..2c09979
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/PluginVersion.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Application\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+use Zend\Http\Client;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(name="plugin_version")
+ */
+class PluginVersion extends Base\PluginVersion {
+
+    public function setupUrl() {
+        $url = explode('/', $this->plugin->getUrl());
+        array_pop($url);
+        array_push($url, $this->version);
+        $baseUrl = implode('/', $url).'/';
+        $this->setUrl($baseUrl.$this->plugin->getArtifactId().'-'.$this->version.$this->_getBinaryExtension($baseUrl));
+    }
+    
+    public function addNbVersion($version) {
+        $this->nbVersionsPluginVersions[] = $version;
+    }
+    
+    private function _getBinaryExtension($baseUrl) {
+        // there could be either .nbm or .jar, so check both
+        $extension = array('.nbm', '.jar');
+        $found = null;
+        foreach($extension as $ext) {
+            $path = $baseUrl.$this->plugin->getArtifactId().'-'.$this->version.$ext;
+            $client = new Client($path, array(
+                'maxredirects' => 0,
+                'timeout' => 30
+            ));
+            $client->setMethod('HEAD');
+            $response = $client->send();
+            if ($response->isSuccess()) {
+                return $ext;
+            }
+        }
+        throw new \Exception('Nbm nor jar binary found on '.$baseUrl);
+    }
+}
diff --git a/pp3/module/Application/src/Application/Entity/Verification.php b/pp3/module/Application/src/Application/Entity/Verification.php
new file mode 100644
index 0000000..c003f89
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Verification.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Application\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+use Application\Entity\VerificationRequest;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(name="verification")
+ */
+class Verification extends Base\Verification {
+
+    const STATUS_REQUESTED = 0;
+    const STATUS_PENDING = 2;
+    const STATUS_GO = 1;
+    const STATUS_NOGO = -1;
+
+    const GO_VOTES_MIN = 2;
+
+    public function addVerificationRequest($req) {
+        $this->verification_requests[] = $req;
+    }
+    
+    public function createRequests($verifiers, $plugin) {
+        foreach($verifiers as $verifier) {
+            $req = new VerificationRequest();
+            $req->setCreatedAt(new \DateTime('now'));
+            $req->setVerification($this);
+            $req->setVerifier($verifier);
+            $req->setVote(VerificationRequest::VOTE_UNDECIDED);
+            $this->addVerificationRequest($req);
+            $req->sendVerificationMail($plugin);
+        }
+    }
+
+    public function getStatusBadgeClass() {
+        if ($this->status === self::STATUS_NOGO) {
+            return 'badge-red';
+        } elseif ($this->status === self::STATUS_GO) {
+            return 'badge-green';
+        }
+    }
+
+    public function getStatusBadgeTitle() {
+        if ($this->status === self::STATUS_NOGO) {
+            return 'NoGo';
+        } elseif ($this->status === self::STATUS_GO) {
+            return 'Go';
+        }
+        return 'Pending';
+    }
+
+    public function resolveStatus($votesBreakdown) {
+        // rule: PASSED = 0 NoGO AND >=2 Go Votes
+        $noGos = $votesBreakdown[VerificationRequest::VOTE_NOGO];
+        $gos = $votesBreakdown[VerificationRequest::VOTE_GO];
+        $undecided = $votesBreakdown[VerificationRequest::VOTE_UNDECIDED];
+        if (count($noGos)) {
+            $this->status = self::STATUS_NOGO;
+            return $this->status;
+        } 
+        if (count($gos) >= self::GO_VOTES_MIN) {
+            $this->status = self::STATUS_GO;
+            return $this->status;
+        }
+        $this->status = self::STATUS_PENDING;
+        return $this->status;
+    }
+}
diff --git a/pp3/module/Application/src/Application/Entity/VerificationRequest.php b/pp3/module/Application/src/Application/Entity/VerificationRequest.php
new file mode 100644
index 0000000..e2525d2
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/VerificationRequest.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace Application\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+use Zend\Mail;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(name="verification_request")
+ */
+class VerificationRequest extends Base\VerificationRequest {
+
+    const VOTE_GO = 1;
+    const VOTE_NOGO = -1;
+    const VOTE_UNDECIDED = 0;
+
+    public function sendVerificationMail($plugin) {
+        // TODO - remove when we have auth ready
+        return;
+
+        $body = 'Hello verifier,
+
+this is to inform you about new verification request requiring your immediate attention.
+
+Plugin: '.$plugin->getName().'
+NetBeans version: '.$this->getVerification()->getNbVersionPluginVersion()->getNbVersion()->getVersion().'
+
+Please login to the NetBeans Plugin Portal at your earliest convenience, test the plugin above in Apache NetBeans IDE it was written for and either Approve or Reject publishing the plugin on the target Plugin Portal Update Center. The testing should validate that the plugin can be installed, deactivated, activated and uninstalled smoothly. If it registers its own Update Center, the uninstallation of the plugin removes the Update Center as well. If you decide to reject a plugin, please in [...]
+
+http://netbeans-vm.apache.org/pluginportal/verification/list
+
+Thanks for your help!
+NetBeans development team
+
+P.S.: This is an automatic email. DO NOT REPLY to this email.';
+
+        $mail = new Mail\Message();
+        $mail->setBody($body);
+        $mail->setFrom('webmaster@netbeans.apache.org', 'NetBeans webmaster');
+        $mail->addTo($this->getVerifier()->getUserId());
+        $mail->setSubject('Verification request for NetBeans plugin: '.$plugin->getName());
+        $transport = new Mail\Transport\Sendmail();
+        
+        $transport->send($mail);
+    }
+
+    public function getVoteBadgeTitle() {
+        if ($this->vote === self::VOTE_NOGO) {
+            return 'NoGo';
+        } elseif ($this->vote === self::VOTE_GO) {
+            return 'Go';
+        }
+        return 'Undecided';
+    }
+
+    public function getVoteBadgeClass() {
+        if ($this->vote === self::VOTE_NOGO) {
+            return 'badge-red';
+        } elseif ($this->vote === self::VOTE_GO) {
+            return 'badge-green';
+        }
+    }
+}
diff --git a/pp3/module/Application/src/Application/Entity/Verifier.php b/pp3/module/Application/src/Application/Entity/Verifier.php
new file mode 100644
index 0000000..6e183fd
--- /dev/null
+++ b/pp3/module/Application/src/Application/Entity/Verifier.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Application\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity
+ * @ORM\Table(name="verifier")
+ */
+class Verifier extends Base\Verifier {
+
+}
diff --git a/pp3/module/Application/src/Application/Factory/AdminControllerFactory.php b/pp3/module/Application/src/Application/Factory/AdminControllerFactory.php
new file mode 100755
index 0000000..bcb8f72
--- /dev/null
+++ b/pp3/module/Application/src/Application/Factory/AdminControllerFactory.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace Application\Factory;
+
+use Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\ServiceManager\FactoryInterface;
+use Application\Controller\AdminController;
+use Application\Repository\PluginRepository;
+use Application\Repository\PluginVersionRepository;
+use Application\Repository\NbVersionPluginVersionRepository;
+use Application\Repository\VerificationRepository;
+use Application\Repository\VerifierRepository;
+use Application\Repository\VerificationRequestRepository;
+use Application\Repository\NbVersionRepository;
+use Application\Repository\CategoryRepository;
+
+class AdminControllerFactory implements FactoryInterface
+{
+    public function createService(ServiceLocatorInterface $serviceLocator) {
+        $em = $serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager');
+
+        $repository = new NbVersionPluginVersionRepository();
+        $repository->setEntityManager($em);
+        
+        $vrepository = new VerificationRepository();
+        $vrepository->setEntityManager($em);
+       
+        $verifierRepository = new VerifierRepository();
+        $verifierRepository->setEntityManager($em);
+
+        $verificationRequestRepository = new VerificationRequestRepository();
+        $verificationRequestRepository->setEntityManager($em);
+
+        $pluginRepository = new PluginRepository();
+        $pluginRepository->setEntityManager($em);
+        
+        $nbVersionRepository = new NbVersionRepository();
+        $nbVersionRepository->setEntityManager($em);
+        
+        $pluginVersionRepository = new PluginVersionRepository();
+        $pluginVersionRepository->setEntityManager($em);
+
+        $categoryRepository = new CategoryRepository();
+        $categoryRepository->setEntityManager($em);
+        
+        $config = $serviceLocator->getServiceLocator()->get('config');
+
+        return new AdminController($pluginRepository, $repository, $vrepository, 
+                                    $verifierRepository, $verificationRequestRepository, 
+                                    $nbVersionRepository, $pluginVersionRepository, $config, $categoryRepository);
+    }
+}
diff --git a/pp3/module/Application/src/Application/Factory/IndexControllerFactory.php b/pp3/module/Application/src/Application/Factory/IndexControllerFactory.php
new file mode 100755
index 0000000..edaf3a1
--- /dev/null
+++ b/pp3/module/Application/src/Application/Factory/IndexControllerFactory.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Application\Factory;
+
+use Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\ServiceManager\FactoryInterface;
+use Application\Repository\PluginRepository;
+use Application\Controller\IndexController;
+use Application\Repository\NbVersionRepository;
+use Application\Repository\CategoryRepository;
+use Application\Repository\PluginVersionRepository;
+
+class IndexControllerFactory implements FactoryInterface
+{
+    public function createService(ServiceLocatorInterface $serviceLocator) {
+        $em = $serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager');
+        $repository = new PluginRepository();
+        $repository->setEntityManager($em);
+        $config = $serviceLocator->getServiceLocator()->get('config');
+        $paginator = $serviceLocator->getServiceLocator()->get('paginator');
+
+        $nbVersionRepository = new NbVersionRepository();
+        $nbVersionRepository->setEntityManager($em);
+
+        $categoryRepository = new CategoryRepository();
+        $categoryRepository->setEntityManager($em);
+
+        $pvRepository = new PluginVersionRepository();
+        $pvRepository->setEntityManager($em);
+
+        return new IndexController($repository, $config, $paginator, $nbVersionRepository, $categoryRepository, $pvRepository);
+    }
+}
diff --git a/pp3/module/Application/src/Application/Factory/LoginControllerFactory.php b/pp3/module/Application/src/Application/Factory/LoginControllerFactory.php
new file mode 100755
index 0000000..f0e2431
--- /dev/null
+++ b/pp3/module/Application/src/Application/Factory/LoginControllerFactory.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Application\Factory;
+
+use Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\ServiceManager\FactoryInterface;
+use Application\Controller\LoginController;
+use Application\Repository\VerifierRepository;
+
+class LoginControllerFactory implements FactoryInterface
+{
+    public function createService(ServiceLocatorInterface $serviceLocator)
+    {
+
+        $config = $serviceLocator->getServiceLocator()->get('config');
+        $em = $serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager');
+        $verifierRepository = new VerifierRepository();
+        $verifierRepository->setEntityManager($em);
+
+        return new LoginController($config, $verifierRepository);
+    }
+}
diff --git a/pp3/module/Application/src/Application/Factory/PluginControllerFactory.php b/pp3/module/Application/src/Application/Factory/PluginControllerFactory.php
new file mode 100755
index 0000000..9f6cce7
--- /dev/null
+++ b/pp3/module/Application/src/Application/Factory/PluginControllerFactory.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Application\Factory;
+
+use Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\ServiceManager\FactoryInterface;
+use Application\Repository\PluginRepository;
+use Application\Repository\PluginVersionRepository;
+use Application\Repository\CategoryRepository;
+use Application\Controller\PluginController;
+use Application\Repository\VerifierRepository;
+
+class PluginControllerFactory implements FactoryInterface
+{
+    public function createService(ServiceLocatorInterface $serviceLocator) {
+        $em = $serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager');
+
+        $repository = new PluginRepository();
+        $repository->setEntityManager($em);
+        
+        $pvRepository = new PluginVersionRepository();
+        $pvRepository->setEntityManager($em);
+
+        $categRepository = new CategoryRepository();
+        $categRepository->setEntityManager($em);
+
+        $config = $serviceLocator->getServiceLocator()->get('config');
+
+        $verifierRepository = new VerifierRepository();
+        $verifierRepository->setEntityManager($em);
+
+        return new PluginController($repository, $pvRepository, $categRepository, $config, $verifierRepository);
+    }
+}
diff --git a/pp3/module/Application/src/Application/Factory/PluginVersionControllerFactory.php b/pp3/module/Application/src/Application/Factory/PluginVersionControllerFactory.php
new file mode 100755
index 0000000..7710901
--- /dev/null
+++ b/pp3/module/Application/src/Application/Factory/PluginVersionControllerFactory.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Application\Factory;
+
+use Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\ServiceManager\FactoryInterface;
+use Application\Repository\PluginRepository;
+use Application\Repository\PluginVersionRepository;
+use Application\Repository\NbVersionRepository;
+use Application\Repository\NbVersionPluginVersionRepository;
+use Application\Controller\PluginVersionController;
+use Application\Repository\VerificationRepository;
+
+class pluginVersionControllerFactory implements FactoryInterface
+{
+    public function createService(ServiceLocatorInterface $serviceLocator) {
+        $em = $serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager');
+        
+        $repository = new PluginRepository();
+        $repository->setEntityManager($em);
+        $pvRepository = new PluginVersionRepository();
+        $pvRepository->setEntityManager($em);
+        $nbvRepository = new NbVersionRepository();
+        $nbvRepository->setEntityManager($em);        
+        $nbVersionPluginVersionRepo = new NbVersionPluginVersionRepository();
+        $nbVersionPluginVersionRepo->setEntityManager($em);
+        $config = $serviceLocator->getServiceLocator()->get('config');
+        $vrepository = new VerificationRepository();
+        $vrepository->setEntityManager($em);
+
+
+        return new PluginVersionController($repository, $pvRepository, $nbvRepository, $nbVersionPluginVersionRepo, $config, $vrepository);
+    }
+}
diff --git a/pp3/module/Application/src/Application/Factory/VerificationControllerFactory.php b/pp3/module/Application/src/Application/Factory/VerificationControllerFactory.php
new file mode 100755
index 0000000..64dc946
--- /dev/null
+++ b/pp3/module/Application/src/Application/Factory/VerificationControllerFactory.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Application\Factory;
+
+use Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\ServiceManager\FactoryInterface;
+use Application\Controller\VerificationController;
+use Application\Repository\NbVersionPluginVersionRepository;
+use Application\Repository\VerificationRepository;
+use Application\Repository\VerifierRepository;
+use Application\Repository\VerificationRequestRepository;
+use Application\Repository\PluginVersionRepository;
+
+class VerificationControllerFactory implements FactoryInterface
+{
+    public function createService(ServiceLocatorInterface $serviceLocator) {
+        $em = $serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager');
+
+        $repository = new NbVersionPluginVersionRepository();
+        $repository->setEntityManager($em);
+        
+        $vrepository = new VerificationRepository();
+        $vrepository->setEntityManager($em);
+       
+        $verifierRepository = new VerifierRepository();
+        $verifierRepository->setEntityManager($em);
+
+        $verificationRequestRepository = new VerificationRequestRepository();
+        $verificationRequestRepository->setEntityManager($em);
+        $config = $serviceLocator->getServiceLocator()->get('config');
+
+        $pluginVersionRepository = new PluginVersionRepository();
+        $pluginVersionRepository->setEntityManager($em);
+
+        return new VerificationController($repository, $vrepository, $verifierRepository, $verificationRequestRepository, $config, $pluginVersionRepository);
+    }
+}
diff --git a/pp3/module/Application/src/Application/Pp/Catalog.php b/pp3/module/Application/src/Application/Pp/Catalog.php
new file mode 100644
index 0000000..2a805d9
--- /dev/null
+++ b/pp3/module/Application/src/Application/Pp/Catalog.php
@@ -0,0 +1,94 @@
+<?php
+namespace Application\Pp;
+
+class Catalog {
+    const CATALOG_FILE_NAME = 'catalog.xml';
+    const CATALOG_FILE_NAME_EXPERIMENTAL = 'catalog-experimental.xml';
+
+    const REQ_ATTRS_MODULE_codenamebase = 'codenamebase';
+    const REQ_ATTRS_MODULE_distribution = 'distribution';
+    const REQ_ATTRS_MODULE_downloadsize = 'downloadsize';
+    
+    const REQ_ATTRS_MANIFEST_OpenIDE_Module = 'OpenIDE-Module';
+    const REQ_ATTRS_MANIFEST_OpenIDE_Module_Name = 'OpenIDE-Module-Name';
+    const REQ_ATTRS_MANIFEST_OpenIDE_Module_Specification_Version = 'OpenIDE-Module-Specification-Version';
+    
+    private $_items;
+    private $_version;
+    private $_isExperimental;
+    private $_downloadPath;
+
+    public function __construct($version, $items, $isExperimental = false, $dtdPath, $downloadPath) {
+        $this->_version = $version;     
+        $this->_items = $items;     
+        $this->_isExperimental = $isExperimental;
+        $this->_dtdPath = $dtdPath;
+        $this->_downloadPath = $downloadPath;
+    }
+
+    public function asXml($valiadte = true) {
+        $implementation = new \DOMImplementation();
+        $dtd = $implementation->createDocumentType('module_updates',
+                                    '-//NetBeans//DTD Autoupdate Catalog 2.6//EN',
+                                    $this->_dtdPath);
+
+        $xml = $implementation->createDocument('', '', $dtd);
+        //$xml = new \DomDocument('1.0', 'UTF-8');       
+        $modulesEl = $xml->createElement('module_updates');
+        $d = new \DateTime('now');
+        $modulesEl->setAttribute('timestamp', $d->format('s/i/h/d/m/Y'));
+        
+        $licenses = array();
+
+        foreach ($this->_items as $item) {
+            $moduleElement = $xml->createElement('module');
+            $moduleElement->setAttribute(self::REQ_ATTRS_MODULE_codenamebase, $item->getPlugin()->getArtifactId());
+            $moduleElement->setAttribute(self::REQ_ATTRS_MODULE_distribution, $this->_downloadPath.$item->getId());
+            $moduleElement->setAttribute(self::REQ_ATTRS_MODULE_downloadsize, '1024');
+            $moduleElement->setAttribute('targetcluster', 'nbms');            
+            $moduleElement->setAttribute('moduleauthor', $item->getPlugin()->getAuthor());            
+            
+            $manifestElement =$xml->createElement('manifest');  
+            $manifestElement->setAttribute(self::REQ_ATTRS_MANIFEST_OpenIDE_Module, $item->getPlugin()->getArtifactId());            
+            $manifestElement->setAttribute(self::REQ_ATTRS_MANIFEST_OpenIDE_Module_Name, $item->getPlugin()->getName());            
+            $manifestElement->setAttribute(self::REQ_ATTRS_MANIFEST_OpenIDE_Module_Specification_Version, $item->getVersion());            
+            $manifestElement->setAttribute('OpenIDE-Module-Long-Description', $item->getPlugin()->getDescription());            
+
+            $moduleElement->appendChild($manifestElement);
+            $modulesEl->appendChild($moduleElement);
+        }
+        
+        $xml->appendChild($modulesEl);
+        if ($valiadte) {
+            libxml_use_internal_errors(true);
+            if (!$xml->validate()) {
+                $msg = [];
+                foreach (libxml_get_errors() as $error) {
+                    array_push($msg, $error->message);
+                }
+                libxml_clear_errors();
+                throw new \Exception('Catalog for '.$this->_version.' is not valid:<br/>'.implode('<br/>', $msg)); 
+            }
+            libxml_use_internal_errors(false);
+        }    
+        $xml->formatOutput = TRUE;
+        return $xml->saveXML();
+    }
+
+    public function storeXml($destinationFolder, $xml) {
+        $filename = $this->_isExperimental ? self::CATALOG_FILE_NAME_EXPERIMENTAL : self::CATALOG_FILE_NAME;
+        $path = $destinationFolder.'/'.$this->_version.'/'.$filename;
+        if(!file_exists(dirname($path))) {
+            mkdir(dirname($path), 0777, true);
+        }
+        if (!file_put_contents($path, $xml)) {
+            throw new \Exception('Unable to save catalog on path '.$path); 
+        }
+        // save also .gz
+        $gz =gzopen($path.'.gz', 'w9');
+        gzwrite($gz, $xml);
+        gzclose($gz);
+        return true;       
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Pp/MavenDataLoader.php b/pp3/module/Application/src/Application/Pp/MavenDataLoader.php
new file mode 100644
index 0000000..704a820
--- /dev/null
+++ b/pp3/module/Application/src/Application/Pp/MavenDataLoader.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Application\Pp;
+
+use Zend\Http\Client;
+
+/**
+ * Description of MavenDataLoader
+ *
+ * @author honza
+ */
+class MavenDataLoader {
+
+    public function getData($plugin) {
+        $xmlData = $this->_fetchData($plugin->getUrl());
+        if ($xmlData) {
+            return $this->_xmlToArray($xmlData);
+        }
+    }
+
+    public function getReleaseData($plugin) {
+        $url = str_replace('maven-metadata.xml', $plugin->getReleaseVersion(), $plugin->getUrl()).'/'.$plugin->getArtifactId().'-'.$plugin->getReleaseVersion().'.pom';
+        $xmlData = $this->_fetchData($url);
+        if ($xmlData) {
+            return $this->_xmlToArray($xmlData);
+        }
+    }
+
+
+    private function _fetchData($url) {
+        $client = new Client($url, array(
+            'maxredirects' => 0,
+            'timeout' => 30
+        ));
+        $response = $client->send();
+        if ($response->isSuccess()) {
+            return $response->getBody();
+        }
+        throw new \Exception('Unable to fetch metadata file from '.$url);
+    }
+
+    private function _xmlToArray($xmlstring) {
+        $xml = simplexml_load_string($xmlstring, null, LIBXML_NOCDATA);
+        $json = json_encode($xml);
+        return json_decode($json, TRUE);
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Repository/CategoryRepository.php b/pp3/module/Application/src/Application/Repository/CategoryRepository.php
new file mode 100644
index 0000000..6a14fa8
--- /dev/null
+++ b/pp3/module/Application/src/Application/Repository/CategoryRepository.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Application\Repository;
+
+class CategoryRepository extends DoctrineEntityRepository {
+
+    public function getEntityRepository() {
+        if (null === $this->entityRepository) {
+            $this->setEntityRepository($this->getEntityManager()->getRepository('Application\Entity\Category'));
+        }
+        return $this->entityRepository;
+    }
+
+    public function getAllCategoriesSortByName() {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('category')
+        ->from('Application\Entity\Category', 'category')       
+        ->orderBy('category.name', 'ASC');  
+        return $queryBuilder->getQuery()->getResult();  
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Repository/DoctrineEntityRepository.php b/pp3/module/Application/src/Application/Repository/DoctrineEntityRepository.php
new file mode 100755
index 0000000..d052264
--- /dev/null
+++ b/pp3/module/Application/src/Application/Repository/DoctrineEntityRepository.php
@@ -0,0 +1,158 @@
+<?php
+namespace Application\Repository;
+
+use Zend\EventManager\EventManagerAwareInterface;
+use Zend\EventManager\EventManagerInterface;
+use Zend\ServiceManager\ServiceManagerAwareInterface;
+use Zend\ServiceManager\ServiceManager;
+use Doctrine\ORM\EntityManager;
+use Doctrine\ORM\EntityRepository;
+
+class DoctrineEntityRepository implements
+    ServiceManagerAwareInterface,
+    EventManagerAwareInterface
+{
+    protected $serviceManager;
+    protected $eventManager;
+    protected $entityManager;
+    protected $entityRepository;
+
+
+    /**
+     * Returns all Entities
+     *
+     * @return EntityRepository
+     */
+    public function findAll()
+    {
+//        $this->getEventManager()->trigger(__FUNCTION__ . '.pre', $this, array('entities' => $entities));
+        $entities = $this->getEntityRepository()->findAll();
+//        $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array('entities' => $entities));
+        return $entities;
+    }    
+
+    public function find($id) {
+        return $this->getEntityRepository()->find($id);
+    }
+
+    public function flush() {
+        $this->getEntityManager()->flush();
+    }
+    
+
+    public function remove($entity) {
+        $this->getEntityManager()->remove($entity);
+        $this->getEntityManager()->flush();
+    }
+
+    public function findByQuery(\Closure $query)
+    {
+        $queryBuilder = $this->getEntityRepository()->createQueryBuilder('entity');
+        $currentQuery = call_user_func($query, $queryBuilder);
+       // \Zend\Debug\Debug::dump($currentQuery->getQuery());
+        return $currentQuery->getQuery()->getResult();
+    }
+
+    /**
+     * Persists and Entity into the Repository
+     *
+     * @param Entity $entity
+     * @return Entity
+     */
+    public function persist($entity)
+    {
+//        $this->getEventManager()->trigger(__FUNCTION__ . '.pre', $this, array('entity'=>$entity));
+        $this->getEntityManager()->persist($entity);
+        $this->getEntityManager()->flush();
+//        $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array('entity'=>$entity));
+
+        return $entity;
+    }
+
+    /**
+     * Merge and Entity into the Repository
+     *
+     * @param Entity $entity
+     * @return Entity
+     */
+    public function merge($entity)
+    {
+        $this->getEntityManager()->merge($entity);
+        $this->getEntityManager()->flush();
+
+        return $entity;
+    }
+
+    /**
+     * @param \Doctrine\ORM\EntityRepository $entityRepository
+     * @return \Haushaltportal\Service\DoctrineEntityRepository
+     */
+    public function setEntityRepository(EntityRepository $entityRepository)
+    {
+        $this->entityRepository = $entityRepository;
+        return $this;
+    }
+
+    /**
+     * @param EntityManager $entityManager
+     * @return \Haushaltportal\Service\DoctrineEntityRepository
+     */
+    public function setEntityManager(EntityManager $entityManager)
+    {
+        $this->entityManager = $entityManager;
+        return $this;
+    }
+
+    /**
+     * @return EntityManager
+     */
+    public function getEntityManager()
+    {
+        return $this->entityManager;
+    }
+
+    /**
+     * Inject an EventManager instance
+     *
+     * @param  EventManagerInterface $eventManager
+     * @return \Haushaltportal\Service\DoctrineEntityRepository
+     */
+    public function setEventManager(EventManagerInterface $eventManager)
+    {
+        $this->eventManager = $eventManager;
+        return $this;
+    }
+
+    /**
+     * Retrieve the event manager
+     * Lazy-loads an EventManager instance if none registered.
+     *
+     * @return EventManagerInterface
+     */
+    public function getEventManager()
+    {
+        return $this->eventManager;
+    }
+
+    /**
+     * Set service manager
+     *
+     * @param ServiceManager $serviceManager
+     * @return \Haushaltportal\Service\DoctrineEntityRepository
+     */
+    public function setServiceManager(ServiceManager $serviceManager)
+    {
+        $this->serviceManager = $serviceManager;
+        return $this;
+    }
+
+    /**
+     * Get service manager
+     *
+     * @return ServiceManager
+     */
+    public function getServiceManager()
+    {
+        return $this->serviceManager;
+    }
+}
\ No newline at end of file
diff --git a/pp3/module/Application/src/Application/Repository/NbVersionPluginVersionRepository.php b/pp3/module/Application/src/Application/Repository/NbVersionPluginVersionRepository.php
new file mode 100644
index 0000000..bf04e3b
--- /dev/null
+++ b/pp3/module/Application/src/Application/Repository/NbVersionPluginVersionRepository.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Application\Repository;
+
+class NbVersionPluginVersionRepository extends DoctrineEntityRepository {
+
+    public function getEntityRepository() {
+        if (null === $this->entityRepository) {
+            $this->setEntityRepository($this->getEntityManager()->getRepository('Application\Entity\NbVersionPluginVersion'));
+        }
+        return $this->entityRepository;
+    }    
+
+    public function removeByNbVersionId($id) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->delete('Application\Entity\NbVersionPluginVersion', 'nbvpv')     
+        ->where('nbvpv.nb_version_id = :id')
+        ->setParameter('id', $id)
+        ->getQuery()->execute(); ;  
+    }
+}
diff --git a/pp3/module/Application/src/Application/Repository/NbVersionRepository.php b/pp3/module/Application/src/Application/Repository/NbVersionRepository.php
new file mode 100644
index 0000000..73c2a2c
--- /dev/null
+++ b/pp3/module/Application/src/Application/Repository/NbVersionRepository.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Application\Repository;
+
+class NbVersionRepository extends DoctrineEntityRepository {
+
+    public function getEntityRepository() {
+        if (null === $this->entityRepository) {
+            $this->setEntityRepository($this->getEntityManager()->getRepository('Application\Entity\NbVersion'));
+        }
+        return $this->entityRepository;
+    }    
+
+    public function findOneBy($column, $value) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('nbVersion')
+        ->from('Application\Entity\NbVersion', 'nbVersion')       
+        ->where('nbVersion.'.$column.' = :value')
+        ->setParameter('value', $value);    
+
+        return $queryBuilder->getQuery()->getOneOrNullResult();    
+    }
+
+    public function getVerifiedNbVersionIdsForPlugin($pluginId) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('nbv.id, nbv.version')
+        ->from('Application\Entity\NbVersion', 'nbv')
+        ->join('nbv.nbVersionsPluginVersions', 'nbvpv')
+        ->join('nbvpv.pluginVersion', 'pv')
+        ->join('pv.plugin p WITH p.id = :pid')
+        ->join('nbvpv.verification v WITH v.status >= 0')
+        ->setParameter('pid', $pluginId)
+        ->groupBy('nbv.id');
+
+        return $queryBuilder->getQuery()->getResult();
+        // return $queryBuilder->getQuery()->getSQL();
+    }
+}
diff --git a/pp3/module/Application/src/Application/Repository/PluginRepository.php b/pp3/module/Application/src/Application/Repository/PluginRepository.php
new file mode 100644
index 0000000..c743b47
--- /dev/null
+++ b/pp3/module/Application/src/Application/Repository/PluginRepository.php
@@ -0,0 +1,130 @@
+<?php
+
+namespace Application\Repository;
+
+class PluginRepository extends DoctrineEntityRepository {
+
+    public function getEntityRepository() {
+        if (null === $this->entityRepository) {
+            $this->setEntityRepository($this->getEntityManager()->getRepository('Application\Entity\Plugin'));
+        }
+        return $this->entityRepository;
+    }
+
+    public function getPluginsByArtifact($art, $grp) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('p')
+        ->from('Application\Entity\Plugin', 'p')
+        ->where('p.artifactid = :art')
+        ->andWhere('p.groupid = :grp')
+        ->setParameter('art', $art)
+        ->setParameter('grp', $grp);
+            
+        return $queryBuilder->getQuery()->getResult();
+    }
+
+
+    public function getTopNDownloadedPublic($n = 5) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('p')
+        ->from('Application\Entity\Plugin', 'p')
+        ->where('p.status = :status')
+        ->setParameter('status', \Application\Entity\Plugin::STATUS_PUBLIC)
+        ->orderBy('p.downloads', 'DESC')
+        ->setMaxResults($n);
+            
+        return $queryBuilder->getQuery()->getResult();
+    }
+
+    public function getLatestNPublic($n = 5) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('p')
+        ->from('Application\Entity\Plugin', 'p')
+        ->where('p.status = :status')
+        ->setParameter('status', \Application\Entity\Plugin::STATUS_PUBLIC)
+        ->orderBy('p.last_updated_at', 'DESC')
+        ->setMaxResults($n);
+            
+        return $queryBuilder->getQuery()->getResult();
+    }
+
+    public function getPluginsByAuthor($author) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('p, v, nbvPv, nbv, verif')
+        ->from('Application\Entity\Plugin', 'p')
+        ->leftJoin('p.versions', 'v')
+        ->leftJoin('v.nbVersionsPluginVersions', 'nbvPv')
+        ->leftJoin('nbvPv.nbVersion', 'nbv')
+        ->leftJoin('nbvPv.verification', 'verif')
+        ->where('p.author = :author')->orderBy('p.id', 'DESC')
+        ->setParameter('author', $author);
+        return $queryBuilder->getQuery()->getResult();        
+    }
+
+    public function getPluginsByStatus($status) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('p, v, nbvPv, nbv')
+        ->from('Application\Entity\Plugin', 'p')
+        ->leftJoin('p.versions', 'v')
+        ->leftJoin('v.nbVersionsPluginVersions', 'nbvPv')
+        ->leftJoin('nbvPv.nbVersion', 'nbv')     
+        ->where('p.status = :status')->orderBy('p.id', 'ASC')
+        ->setParameter('status', $status);
+        return $queryBuilder->getQuery()->getResult();
+    }
+
+    public function getPluginsByName($name) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('p, v, nbvPv, nbv')
+        ->from('Application\Entity\Plugin', 'p')
+        ->leftJoin('p.versions', 'v')
+        ->leftJoin('v.nbVersionsPluginVersions', 'nbvPv')
+        ->leftJoin('nbvPv.nbVersion', 'nbv')     
+        ->where('(p.name LIKE :name) OR (p.author LIKE :name)')->orderBy('p.id', 'ASC')
+        ->setParameter('name', '%'.$name.'%');
+        return $queryBuilder->getQuery()->getResult();
+    }
+
+    public function getPublicPluginsByNameQB($name, $cat, $nbv) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('p, cat')
+        ->from('Application\Entity\Plugin', 'p')
+        ->leftJoin('p.versions', 'v')
+        ->leftJoin('v.nbVersionsPluginVersions', 'nbvPv')
+        ->leftJoin('nbvPv.verification', 'verif')
+        ->leftJoin('nbvPv.nbVersion', 'nbv')
+        ->leftJoin('p.categories', 'cat')
+        ->where('p.status = :status')
+        ->setParameter('status', \Application\Entity\Plugin::STATUS_PUBLIC);
+        if ($name) {
+            $queryBuilder->andWhere('(p.name LIKE :name OR p.artifactid LIKE :name OR p.author LIKE :name OR p.short_description LIKE :name OR p.description LIKE :name
+            OR p.license LIKE :name OR nbv.version LIKE :name OR cat.name LIKE :name)')->setParameter('name', '%'.$name.'%');
+        }     
+        //$queryBuilder->orderBy('p.name', 'ASC');
+        if (!empty($cat)) {
+            $queryBuilder->andWhere('cat.name = :cat')->setParameter('cat', $cat);
+        }
+        if (!empty($nbv)) {
+            $queryBuilder->andWhere('nbv.version = :nbv')->setParameter('nbv', $nbv);
+        }
+            
+        return $queryBuilder;
+    }
+
+    public function getPublicPluginById($id) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('p, v, nbvPv, nbv, verif, cat')
+        ->from('Application\Entity\Plugin', 'p')
+        ->leftJoin('p.versions', 'v')
+        ->leftJoin('v.nbVersionsPluginVersions', 'nbvPv')
+        ->leftJoin('nbvPv.verification', 'verif')
+        ->leftJoin('nbvPv.nbVersion', 'nbv')
+        ->leftJoin('p.categories', 'cat')
+        ->where('p.status = :status')
+        ->setParameter('status', \Application\Entity\Plugin::STATUS_PUBLIC)
+        ->andWhere('p.id = :id')
+        ->setParameter('id', $id);
+            
+        return $queryBuilder->getQuery()->getOneOrNullResult();
+    }
+}
diff --git a/pp3/module/Application/src/Application/Repository/PluginVersionRepository.php b/pp3/module/Application/src/Application/Repository/PluginVersionRepository.php
new file mode 100644
index 0000000..5707085
--- /dev/null
+++ b/pp3/module/Application/src/Application/Repository/PluginVersionRepository.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Application\Repository;
+
+class PluginVersionRepository extends DoctrineEntityRepository {
+
+    public function getEntityRepository() {
+        if (null === $this->entityRepository) {
+            $this->setEntityRepository($this->getEntityManager()->getRepository('Application\Entity\PluginVersion'));
+        }
+        return $this->entityRepository;
+    }
+
+    public function getVerifiedVersionsByNbVersion($nbVersion) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('pluginVersion, plugin')
+        ->from('Application\Entity\PluginVersion', 'pluginVersion')
+        ->join('pluginVersion.plugin', 'plugin')
+        ->join('pluginVersion.nbVersionsPluginVersions', 'nbVersionsPluginVersions')
+        ->join('nbVersionsPluginVersions.nbVersion', 'nbVersion')
+        ->join('nbVersionsPluginVersions.verification', 'verification')
+        ->where('nbVersion.version = :nbversion')
+        ->andWhere('verification.status = :verifstatus')
+        ->andWhere('plugin.status = :pluginstatus')
+        ->orderBy('pluginVersion.id', 'ASC')
+        ->setParameter('nbversion', $nbVersion)
+        ->setParameter('verifstatus', \Application\Entity\Verification::STATUS_GO)
+        ->setParameter('pluginstatus', \Application\Entity\Plugin::STATUS_PUBLIC);
+        
+        return $queryBuilder->getQuery()->getResult();    
+    }
+
+    public function getNonVerifiedVersionsByNbVersion($nbVersion) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('pluginVersion, plugin')
+        ->from('Application\Entity\PluginVersion', 'pluginVersion')
+        ->join('pluginVersion.plugin', 'plugin')
+        ->join('pluginVersion.nbVersionsPluginVersions', 'nbVersionsPluginVersions')
+        ->join('nbVersionsPluginVersions.nbVersion', 'nbVersion')
+        ->where('nbVersion.version = :nbversion')
+        ->andWhere('plugin.status = :pluginstatus')
+        ->orderBy('pluginVersion.id', 'ASC')
+        ->setParameter('nbversion', $nbVersion)
+        ->setParameter('pluginstatus', \Application\Entity\Plugin::STATUS_PUBLIC);
+        
+        return $queryBuilder->getQuery()->getResult();    
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Repository/VerificationRepository.php b/pp3/module/Application/src/Application/Repository/VerificationRepository.php
new file mode 100644
index 0000000..0724ca3
--- /dev/null
+++ b/pp3/module/Application/src/Application/Repository/VerificationRepository.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Application\Repository;
+
+class VerificationRepository extends DoctrineEntityRepository {
+
+    public function getEntityRepository() {
+        if (null === $this->entityRepository) {
+            $this->setEntityRepository($this->getEntityManager()->getRepository('Application\Entity\Verification'));
+        }
+        return $this->entityRepository;
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Repository/VerificationRequestRepository.php b/pp3/module/Application/src/Application/Repository/VerificationRequestRepository.php
new file mode 100644
index 0000000..186e10a
--- /dev/null
+++ b/pp3/module/Application/src/Application/Repository/VerificationRequestRepository.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Application\Repository;
+
+class VerificationRequestRepository extends DoctrineEntityRepository {
+
+    public function getEntityRepository() {
+        if (null === $this->entityRepository) {
+            $this->setEntityRepository($this->getEntityManager()->getRepository('Application\Entity\VerificationRequest'));
+        }
+        return $this->entityRepository;
+    }
+
+    public function getVotesBreakdownForVerification($verificationId) {
+        return array(
+            \Application\Entity\VerificationRequest::VOTE_GO => $this->getVotedRequestsForVerification($verificationId, \Application\Entity\VerificationRequest::VOTE_GO),
+            \Application\Entity\VerificationRequest::VOTE_NOGO => $this->getVotedRequestsForVerification($verificationId, \Application\Entity\VerificationRequest::VOTE_NOGO),
+            \Application\Entity\VerificationRequest::VOTE_UNDECIDED => $this->getVotedRequestsForVerification($verificationId, \Application\Entity\VerificationRequest::VOTE_UNDECIDED),
+        );
+    }
+
+    public function getVerificationRequestsForVerifier($verifierId) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('vrq, verification, verifier, nbVersionPluginVersion, pluginVersion, plugin, nbVersion')
+        ->from('Application\Entity\VerificationRequest', 'vrq')
+        ->join('vrq.verifier', 'verifier')
+        ->join('vrq.verification', 'verification')
+        ->join('verification.nbVersionPluginVersion', 'nbVersionPluginVersion')
+        ->join('nbVersionPluginVersion.pluginVersion', 'pluginVersion')
+        ->join('nbVersionPluginVersion.nbVersion', 'nbVersion')
+        ->join('pluginVersion.plugin', 'plugin')
+        ->where('verifier.user_id = :userId')
+        ->andWhere('verification.status IN (:status)')
+        ->orderBy('vrq.created_at', 'DESC')
+        ->setParameter('status', array(\Application\Entity\Verification::STATUS_REQUESTED, \Application\Entity\Verification::STATUS_PENDING))
+        ->setParameter('userId', $verifierId);
+        return $queryBuilder->getQuery()->getResult();    
+    }
+
+    public function getVotedRequestsForVerification($verificationId, $vote) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('vrq')
+        ->from('Application\Entity\VerificationRequest', 'vrq')       
+        ->where('vrq.verification_id = :vid')
+        ->andWhere('vrq.vote = :vote')
+        ->setParameter('vid', $verificationId)
+        ->setParameter('vote', $vote);
+        return $queryBuilder->getQuery()->getResult();  
+    }
+    
+    public function deleteRequestsOfVerification($verificationId) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->delete('Application\Entity\VerificationRequest', 'vrq')
+        ->where('vrq.verification_id = :vid')
+        ->setParameter('vid', $verificationId);
+        return $queryBuilder->getQuery()->getResult();  
+    }
+
+}
diff --git a/pp3/module/Application/src/Application/Repository/VerifierRepository.php b/pp3/module/Application/src/Application/Repository/VerifierRepository.php
new file mode 100644
index 0000000..fb7e468
--- /dev/null
+++ b/pp3/module/Application/src/Application/Repository/VerifierRepository.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Application\Repository;
+
+class VerifierRepository extends DoctrineEntityRepository {
+
+    public function getEntityRepository() {
+        if (null === $this->entityRepository) {
+            $this->setEntityRepository($this->getEntityManager()->getRepository('Application\Entity\Verifier'));
+        }
+        return $this->entityRepository;
+    }
+
+    public function findOneBy($column, $value) {
+        $queryBuilder = $this->getEntityManager()->createQueryBuilder();
+        $queryBuilder->select('verifier')
+        ->from('Application\Entity\Verifier', 'verifier')       
+        ->where('verifier.'.$column.' = :value')
+        ->setParameter('value', $value);    
+
+        return $queryBuilder->getQuery()->getOneOrNullResult();    
+    }
+}
diff --git a/pp3/module/Application/view/application/admin/_nav.phtml b/pp3/module/Application/view/application/admin/_nav.phtml
new file mode 100644
index 0000000..abfcdb5
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/_nav.phtml
@@ -0,0 +1,10 @@
+<h3>Admin tools</h3>
+<p class="admin-nav">
+<a href="<?= $this->url('admin', array('action' => 'index'))?>">Find & Edit Plugin</a>
+<a href="<?= $this->url('admin', array('action' => 'approve'))?>">Plugins waiting for approval</a>
+<a href="<?= $this->url('admin', array('action' => 'catalog'))?>">Publish catalog</a>
+<a href="<?= $this->url('admin', array('action' => 'verifiers'))?>">Verifiers</a>
+<a href="<?= $this->url('admin', array('action' => 'categories'))?>">Plugin categories</a>
+<a href="<?= $this->url('admin', array('action' => 'nb-versions'))?>">NetBeans versions</a>
+</p>
+<hr/>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/admin/_plugin-listrow.phtml b/pp3/module/Application/view/application/admin/_plugin-listrow.phtml
new file mode 100644
index 0000000..646b64b
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/_plugin-listrow.phtml
@@ -0,0 +1,101 @@
+<?php
+$pluugin = $this->plugin;
+echo '<tr>
+<td style="text-align: center;"><h4><i class="fas '.$plugin->getStatusIconClass().'" title="'.$plugin->getStatusTitle().'"></i></h4></td>
+<td>
+    <h4 class="text-primary">'.$plugin->getName().'</h4>
+    <p>
+        <a class="btn btn-default" href="'.$this->url('admin', array('action' => 'edit'),array('query' => array('id'=>$plugin->getId()))).'" role="button" title="Edit">
+            <i class="fas fa-edit text-primary"></i>
+        </a>
+        <a class="btn btn-default" href="'.$this->url('admin',array('action'=>'index'),array('query' => array('id'=>$plugin->getId(), 'act'=>'delete'))).'" role="button" title="Remove">
+            <i class="fas fa-trash text-danger"></i>
+        </a>
+        <a class="btn btn-default" href="'.$this->url('admin',array('action'=>'index'),array('query' => array('id'=>$plugin->getId(), 'act'=>'sync'))).'" role="button" title="Sync with source manifest.">
+            <i class="fas fa-sync"></i>
+        </a>               
+        <a class="btn btn-default" href="'.$this->url('admin',array('action'=>'index'),array('query' => array('id'=>$plugin->getId(), 'act'=>'publish'))).'" role="button" title="Approve">
+        <i class="fas fa-eye color-green"></i>&nbsp; Approve
+        </a> 
+        <a class="btn btn-default" href="'.$this->url('admin',array('action'=>'index'),array('query' => array('id'=>$plugin->getId(), 'act'=>'hide'))).'" role="button" title="Hide">
+        <i class="fas fa-eye-slash color-red"></i>&nbsp; Hide
+        </a>
+    </p>
+    <p>Status: <b>'.$plugin->getStatusTitle().'</b></p>
+    <div>
+        <p>ArtifactId: <b>'.$plugin->getArtifactId().'</b><p>
+        <p>Author: <b>'.$plugin->getAuthor().'</b><p>
+        <p>
+        <i class="fas fa-asterisk"></i> '.$plugin->getAddedAt()->format('Y-m-d').' &nbsp; &nbsp;
+        <i class="fas fa-edit"></i> '.$plugin->getLastUpdatedAt()->format('Y-m-d').' &nbsp; &nbsp; 
+        <i class="fas fa-download"></i> '.number_format($plugin->getDownloads()).' 
+        </p>                
+    </div>
+    <p>';
+
+foreach ($plugin->getCategories() as $cat) {
+    echo '<span class="badge badge-blue">'.$cat->getName().'</span> &nbsp;';
+}    
+
+echo '</p>
+</td>
+<td>
+    <table class="table table-striped">
+        <thead>
+            <tr>
+            <th scope="col" style="width: 170px;">Plugin Version</th>
+            <th scope="col">NB Versions</th>
+            <th scope="col">Verifications</th>
+            </tr>
+        </thead>
+        <tbody>';
+
+foreach ($plugin->getVersions() as $version) {
+    echo '<tr>
+        <td><span class="badge">'.$version->getVersion().'</span></td>
+        <td>';
+    foreach ($version->getNbVersionsPluginVersions() as $nbvPv) {
+            echo '<span class="badge badge-brown">NB '.$nbvPv->getNbVersion()->getVersion().'</span>&nbsp; ';
+    }    
+    echo '</td>
+        <td>';
+    foreach ($version->getNbVersionsPluginVersions() as $nbvPv) {
+        if ($nbvPv->getVerificationId()) {
+            echo '<a data-toggle="modal" data-target="#logModal'.$nbvPv->getVerificationId().'" href="#"><span class="badge '.$nbvPv->getVerification()->getStatusBadgeClass().'" title="'.$nbvPv->getVerification()->getStatusBadgeTitle().'">
+            NB '.$nbvPv->getNbVersion()->getVersion().' - '.$nbvPv->getVerification()->getStatusBadgeTitle().'</span></a> &nbsp; ';
+            echo ' 
+                    <div class="modal fade" id="logModal'.$nbvPv->getVerificationId().'" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
+                        <div class="modal-dialog" role="document">
+                            <div class="modal-content">
+                            <div class="modal-header">
+                                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                                <h4 class="modal-title" id="myModalLabel">Verification Log of '.$version->getVersion().' plugin version to NB '.$nbvPv->getNbVersion()->getVersion().'</h4>
+                            </div>
+                            <div class="modal-body">
+                                <p><b>Verification status: '.$nbvPv->getVerification()->getStatusBadgeTitle().'</b></p> 
+                                <p>Requested on: '.$nbvPv->getVerification()->getCreatedAt()->format('Y-m-d').'</p><br/>  
+                                <h4>Votes</h4>
+                                <table class="table table-striped">'; 
+                            foreach($nbvPv->getVerification()->getVerificationRequests() as $vrq) {
+                                echo '<tr>
+                                        <td>'.$vrq->getVerifier()->getuserId().'</td>
+                                        <td><span class="badge '.$vrq->getVoteBadgeClass().'" title="'.$vrq->getVoteBadgeTitle().'">'.$vrq->getVoteBadgeTitle().'</span></td>
+                                        <td>'.($vrq->getVotedAt() ? $vrq->getVotedAt()->format('Y-m-d') : '').'</td>
+                                    </tr>';
+                            }
+                            echo'</table></div>
+                            <div class="modal-footer">
+                                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                            </div>
+                            </div>
+                        </div>
+                    </div>';
+        }
+    }
+}
+echo '<td>
+</tr>
+</tbody>
+</table>
+</td>
+</tr>';
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/admin/_pluginRowItem.phtml b/pp3/module/Application/view/application/admin/_pluginRowItem.phtml
new file mode 100644
index 0000000..b4d0d0e
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/_pluginRowItem.phtml
@@ -0,0 +1,26 @@
+<?php
+$versionBadges = array();
+foreach ($plugin->getVersions() as $version) {
+    $versionBadges[]='<span class="badge">'.$version->getVersion().'</span>';
+}
+
+echo '
+<h4 class="text-primary"><a href="'.$this->url('admin', array('action' => 'edit'),array('query' => array('id'=>$plugin->getId()))).'">'.$plugin->getName().'</a></h4>
+<p>
+    '.implode('&nbsp;', $versionBadges).'
+</p>
+<p>ArtifactId: <b>'.$plugin->getArtifactId().'</b><p>
+<p>
+<p>Status: <b>'.$plugin->getStatusTitle().'</b></p>
+<i class="fas fa-user"></i> '.$plugin->getAuthorName().' &nbsp; &nbsp;&nbsp; 
+<i class="fas fa-asterisk"></i> '.$plugin->getAddedAt()->format('Y-m-d').' &nbsp; &nbsp;&nbsp; 
+<i class="fas fa-edit"></i> '.$plugin->getLastUpdatedAt()->format('Y-m-d').'   &nbsp; &nbsp;  &nbsp;            
+<i class="fas fa-file-contract"></i> '.$plugin->getLicense().'
+</p>
+<p>';
+
+foreach ($plugin->getCategories() as $cat) {
+    echo '<span class="badge badge-blue">'.$cat->getName().'</span> &nbsp;';
+}    
+echo '</p>';
+?>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/admin/approve.phtml b/pp3/module/Application/view/application/admin/approve.phtml
new file mode 100644
index 0000000..b73aff5
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/approve.phtml
@@ -0,0 +1,44 @@
+<?= $this->partial('_nav.phtml'); ?>
+<h4>Plugins waiting for approval</h4>
+<p>
+<?= $this->partial('layout/flash.phtml'); ?>
+</p>
+<table class="table table-striped">
+    <thead>
+        <tr>
+            <th>Plugin</th>
+            <th>Description</th>
+            <th>Action</th>
+        </tr>
+    </thead>
+    <tbody>
+<?php
+    foreach ($this->plugins as $plugin) {
+        $versionBadges = array();
+        foreach ($plugin->getVersions() as $version) {
+            $versionBadges[]='<span class="badge">'.$version->getVersion().'</span>';
+        }
+        echo '<tr>
+            <td>
+               '.$this->partial('_pluginRowItem.phtml', array('plugin' => $plugin)).'
+            </td>
+            <td>
+                '.$plugin->getDescription().'
+            </td>
+            <td>
+                <p>
+                <a class="btn btn-success" href="'.$this->url('admin',array('action'=>'approve'),array('query' => array('id'=>$plugin->getId()))).'" role="button" title="Approve">
+                    Approve
+                </a>
+                </p>
+                <p>
+                <a class="btn btn-danger" href="'.$this->url('admin',array('action'=>'delete-pending'),array('query' => array('id'=>$plugin->getId()))).'" role="button" title="Publish">
+                    Delete
+                </a>
+                </p>
+            </td>
+        </tr>';
+    }
+?>
+    </tbody>
+</table>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/admin/catalog.phtml b/pp3/module/Application/view/application/admin/catalog.phtml
new file mode 100644
index 0000000..5471210
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/catalog.phtml
@@ -0,0 +1,27 @@
+<?= $this->partial('_nav.phtml'); ?>
+<h4>Publish catalog</h4>
+<p>
+<?= $this->partial('layout/flash.phtml'); ?>
+</p>
+<table class="table table-striped table-hover">
+<?php
+    foreach ($this->nbVersions as $nbv) {
+        echo '<tr>
+            <td><h4>NB '.$nbv->getVersion().'</h4></td>
+            <td>
+                <a href="'.$this->catalUrlPath.'/'.$nbv->getVersion().'/catalog.xml" target="_blank">View catalog</a><br/>
+                <a href="'.$this->catalUrlPath.'/'.$nbv->getVersion().'/catalog-experimental.xml" target="_blank">View experimental catalog</a>
+            </td>
+            <td>
+                <a class="btn btn-primary" href="'.$this->url('admin',array('action'=>'catalog'),array('query' => array('version'=>$nbv->getVersion()))).'" role="button" title="Approve">
+                    Publish catalog
+                </a>
+                &nbsp;
+                <a class="btn btn-primary" href="'.$this->url('admin',array('action'=>'catalog'),array('query' => array('version'=>$nbv->getVersion(), 'experimental' => true))).'" role="button" title="Approve">
+                Publish experimental catalog
+            </a>
+            </td>
+        </tr>';
+    }
+?>
+</table>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/admin/categories.phtml b/pp3/module/Application/view/application/admin/categories.phtml
new file mode 100644
index 0000000..0d6fc81
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/categories.phtml
@@ -0,0 +1,29 @@
+<?= $this->partial('_nav.phtml'); ?>
+<h4>Plugin categories</h4>
+<p>
+<?= $this->partial('layout/flash.phtml'); ?>
+</p>
+<p>
+<form class="form-inline" method="post" action="">
+  <div class="form-group">
+    <label for="name">New category: </label>
+    <input type="text" class="form-control" name="name" id="name" placeholder="category name" style="width: 300px;" value="">
+  </div>
+  <button type="submit" class="btn btn-primary">Add Category</button>
+</form>
+</p>
+<br/>
+<table class="table table-striped table-hover" style="width: 50%">
+<?php
+    foreach ($this->categories as $c) {
+        echo '<tr>
+            <td><h5>'.$c->getName().'</h5></td>            
+            <td>
+                <a class="btn btn-danger" href="'.$this->url('admin',array('action'=>'categories'),array('query' => array('id'=>$c->getId()))).'" role="button" title="Approve">
+                    Delete
+                </a>
+            </td>
+        </tr>';
+    }
+?>
+</table>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/admin/edit.phtml b/pp3/module/Application/view/application/admin/edit.phtml
new file mode 100644
index 0000000..ef37660
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/edit.phtml
@@ -0,0 +1,12 @@
+<h3>Edit Plugin</h3>
+    <div class="row">
+        <div class="col col-sm-6">
+            <?= $this->partial('layout/flash.phtml'); ?>
+            <form method="post" action="" class="needs-validation" enctype="multipart/form-data">
+            <?= $this->partial('application/plugin/_plugin-form.phtml', array('plugin' => $this->plugin, 'categories' => $this->categories)); ?>
+            <a class="btn btn-secondary" href="<?= $this->url('admin')?>" role="button">Return</a>
+            <button type="submit" class="btn btn-primary">Save Plugin</button>
+            </form>
+            
+        </div>
+    </div>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/admin/index.phtml b/pp3/module/Application/view/application/admin/index.phtml
new file mode 100644
index 0000000..08556e3
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/index.phtml
@@ -0,0 +1,45 @@
+<?= $this->partial('_nav.phtml'); ?>
+<h4>Find and edit plugin</h4>
+<p>
+<?= $this->partial('layout/flash.phtml'); ?>
+</p>
+<form class="form-inline" method="get" action="">
+  <div class="form-group">
+    <!-- <label for="exampleInputName2">Search</label> -->
+    <input type="text" class="form-control" name="search" id="search" placeholder="Search for plugin..." style="width: 300px;" value="<?= $this->search ?>">
+  </div>
+  <button type="submit" class="btn btn-primary">Search</button>
+</form>
+<br/>
+<br/>
+<?php
+if ($this->plugins) {
+    echo '<table class="table table-striped">
+    <thead>
+        <tr>
+            <th></th>
+            <th>Plugin</th>
+            <th>Versions</th>            
+        </tr>
+    </thead>
+        <tbody>';
+
+    foreach($this->plugins as $plugin) {
+        echo $this->partial('application/admin/_plugin-listrow.phtml', array('plugin' => $plugin));
+    }
+    echo '</tbody></table>';
+} else {
+    if ($this->search) {
+        echo '<p>Sorry, no plugins found</p>';
+    }
+}
+
+?>
+<script>
+  $( function() {
+    $( "#search" ).autocomplete({
+      source: "<?= $this->url('admin',array('action'=>'search-autocomplete')) ?>",
+      minLength: 3,      
+    });
+  } );
+</script>
diff --git a/pp3/module/Application/view/application/admin/nb-versions.phtml b/pp3/module/Application/view/application/admin/nb-versions.phtml
new file mode 100644
index 0000000..e824ad6
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/nb-versions.phtml
@@ -0,0 +1,29 @@
+<?= $this->partial('_nav.phtml'); ?>
+<h4>NetBeans versions</h4>
+<p>
+<?= $this->partial('layout/flash.phtml'); ?>
+</p>
+<p>
+<form class="form-inline" method="post" action="">
+  <div class="form-group">
+    <label for="exampleInputName2">New version: </label>
+    <input type="text" class="form-control" name="version" id="search" placeholder="NetBeans version" style="width: 300px;" value="">
+  </div>
+  <button type="submit" class="btn btn-primary">Add version</button>
+</form>
+</p>
+<br/>
+<table class="table table-striped table-hover" style="width: 50%">
+<?php
+    foreach ($this->nbVersions as $v) {
+        echo '<tr>
+            <td><h5>'.$v->getVersion().'</h5></td>            
+            <td>
+                <a class="btn btn-danger" href="'.$this->url('admin',array('action'=>'nb-versions'),array('query' => array('id'=>$v->getId()))).'" role="button" title="Delete">
+                    Delete
+                </a>
+            </td>
+        </tr>';
+    }
+?>
+</table>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/admin/verifiers.phtml b/pp3/module/Application/view/application/admin/verifiers.phtml
new file mode 100644
index 0000000..00bd346
--- /dev/null
+++ b/pp3/module/Application/view/application/admin/verifiers.phtml
@@ -0,0 +1,29 @@
+<?= $this->partial('_nav.phtml'); ?>
+<h4>Verifiers</h4>
+<p>
+<?= $this->partial('layout/flash.phtml'); ?>
+</p>
+<p>
+<form class="form-inline" method="post" action="">
+  <div class="form-group">
+    <label for="exampleInputName2">New verifier: </label>
+    <input type="text" class="form-control" name="userId" id="search" placeholder="User ID" style="width: 300px;" value="">
+  </div>
+  <button type="submit" class="btn btn-primary">Add Verifier</button>
+</form>
+</p>
+<br/>
+<table class="table table-striped table-hover" style="width: 50%">
+<?php
+    foreach ($this->verifiers as $v) {
+        echo '<tr>
+            <td><h5>'.$v->getUserId().'</h5></td>            
+            <td>
+                <a class="btn btn-danger" href="'.$this->url('admin',array('action'=>'verifiers'),array('query' => array('id'=>$v->getId()))).'" role="button" title="Delete">
+                    Delete
+                </a>
+            </td>
+        </tr>';
+    }
+?>
+</table>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/index/catalogue.phtml b/pp3/module/Application/view/application/index/catalogue.phtml
new file mode 100644
index 0000000..545eb9d
--- /dev/null
+++ b/pp3/module/Application/view/application/index/catalogue.phtml
@@ -0,0 +1,83 @@
+<?php
+$h = 'Sorry, no plugin found';
+if ($this->plugin) {
+    $h = $this->plugin->getName();
+} 
+echo '<h3 class="text-primary">'.$h.'</h3>';
+
+if ($plugin) {
+    echo '
+    <div class="row">
+    <div class="col-md-6">
+    <p>
+    <p>ArtifactId: <b>'.$plugin->getArtifactId().'</b> &nbsp;&nbsp;
+    ';
+
+        foreach ($plugin->getVersions() as $v) {
+            echo '<span class="badge">'.$v->getVersion().'</span> &nbsp;';
+        }    
+        
+    echo '</p>
+    <p>Author: <b>'.$plugin->getAuthorName().'</b></p>
+    <p>License: <b>'.$plugin->getLicense().'</b></p>
+    <p>Homepage: <a href="'.$plugin->getHomepage().'">'.$plugin->getHomepage().'</a></p>
+    <p>
+        <i class="fas fa-asterisk"></i> '.$plugin->getAddedAt()->format('Y-m-d').' &nbsp; &nbsp;
+        <i class="fas fa-edit"></i> '.$plugin->getLastUpdatedAt()->format('Y-m-d').' &nbsp; &nbsp;
+        <i class="fas fa-download"></i> '.number_format($plugin->getDownloads()).' 
+    </p>
+    <p>';
+
+        foreach ($plugin->getCategories() as $cat) {
+            echo '<span class="badge badge-blue">'.$cat->getName().'</span> &nbsp;';
+        }    
+    echo '</p> 
+    <br/><h4 class="text-primary">Download matrix</h4>
+    <table class="table table-striped table-hover" style="width:auto">
+    <thead>
+        <tr>
+        <th>Plugin version</th>
+        <th>NetBeans compatible</th>
+        </tr>
+        </thead>
+        <tbody>
+        ';
+        foreach ($plugin->getVersions() as $version) {
+            echo '<tr><td><span class="badge">'.$version->getVersion().'</span></td><td>';
+            foreach ($version->getNbVersionsPluginVersions() as $nbvPv) {
+                echo '<a href="./download?id='.$version->getId().'" title="Download" target="_blank"><span class="badge badge-brown"><i class="fas fa-download"></i> NB '.$nbvPv->getNbVersion()->getVersion().'</span></a> &nbsp; ';
+            }    
+            echo '</td></tr>';
+        }
+        echo '</tbody>
+        </table>
+        </div>
+        <div class="col-md-6">';
+        if($plugin->getImage()) {
+            echo '<div><img src="../data/plugins/'.$plugin->getId().'/'.$plugin->getImage().'" style="max-width: 100%;"/></div>';
+        }    
+    echo '</div>
+        </div>
+    <br/>
+    <div class="panel panel-default">
+    <div class="panel-heading">
+        <h3 class="panel-title">Intro</h3>
+    </div>
+    <div class="panel-body">
+        '.$plugin->getShortDescription().'
+    </div>
+    </div>
+    <br/>
+    <div class="panel panel-default">
+    <div class="panel-heading">
+        <h3 class="panel-title">Description</h3>
+    </div>
+    <div class="panel-body">
+        '.$plugin->getDescription().'
+    </div>
+    </div>
+    <br/>
+    ';
+    
+
+}
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/index/index.phtml b/pp3/module/Application/view/application/index/index.phtml
new file mode 100755
index 0000000..f622f65
--- /dev/null
+++ b/pp3/module/Application/view/application/index/index.phtml
@@ -0,0 +1,145 @@
+
+<div class="row">
+  <div class="col-md-6">
+    <div class="panel panel-default">
+      <div class="panel-heading">
+        <h3 class="panel-title">Most downloaded</h3>
+      </div>
+      <div class="panel-body">
+        <?php
+        $i=1;
+        foreach($this->best as $p) {
+          echo '<p>
+          <h5>'.$i.'. <span class="text-primary"><a href="'.$this->url('catalogue', array(), array('query' => array('id'=>$p->getId()))).'">'.$p->getName().'</a></span> &nbsp; 
+            <i class="fas fa-download"></i> '.number_format($p->getDownloads()).'</h5>
+          </p>';
+          $i++;
+        }
+        ?>
+      </div>
+    </div>
+  </div>
+  <div class="col-md-6">
+    <div class="panel panel-default">
+      <div class="panel-heading">
+        <h3 class="panel-title">Latest updates</h3>
+      </div>
+      <div class="panel-body">
+      <?php
+        $i=1;
+        foreach($this->latest as $p) {
+          echo '<p>
+          <h5>'.$i.'. <span class="text-primary"><a href="'.$this->url('catalogue', array(), array('query' => array('id'=>$p->getId()))).'">'.$p->getName().'</a></span> &nbsp; 
+            '.date_format($p->getLastUpdatedAt(), 'Y-m-d').'</h5>
+          </p>';
+          $i++;
+        }
+        ?>
+      </div>
+    </div>
+  </div>
+</div>
+<br/><br/>
+<form class="form-inline" method="get" action="">
+  <div class="form-group">
+    <label for="search">Search</label>
+    <input type="text" class="form-control" name="search" id="search" 
+    placeholder="Name, description, author, category, license..." style="width: 350px;" value="<?= htmlentities($this->search) ?>">
+  </div>
+  <div class="form-group">
+       <label for="nbvsel">&nbsp; NetBeans version</label>
+       <select id="nbvsel" name="nbv" class="form-control">
+          <option value="">Any</option>
+          <?php
+          foreach($this->versions as $version) {
+              $sel = ($_GET['nbv'] == $version->getVersion())? 'selected' : ''; 
+              echo '<option value="'.$version->getVersion().'" '.$sel.'>'.$version->getVersion().'</option>';
+          }
+          ?>
+       </select>
+  </div>
+  <div class="form-group">
+       <label for="catsel">&nbsp; Category</label>
+       <select id="catsel" name="cat" class="form-control">
+          <option value="">Any</option>
+          <?php
+          foreach($this->categories as $cat) {
+              $sel = ($_GET['cat'] == $cat->getName())? 'selected' : ''; 
+              echo '<option value="'.$cat->getName().'" '.$sel.'>'.$cat->getName().'</option>';
+          }
+          ?>
+       </select>
+  </div>
+  <button type="submit" class="btn btn-primary">Go!</button>
+</form>
+<br/>
+<hr/>
+<p class="text-info">Found <?= number_format($this->paginator->getTotalItemCount())?> plugins.</p>
+<table class="table table-striped">
+  <thead>
+    <tr>
+      <th>Plugin</th>
+      <th>Categories</th>
+      <th>NetBeans compatible</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+<?php
+    foreach($this->paginator as $plugin) {
+        $versionBadges = array();
+        foreach ($plugin->getVersions() as $version) {
+            $versionBadges[]='<span class="badge">'.$version->getVersion().'</span>';
+        }
+
+        echo '<tr>
+        <td>
+            <h4 class="text-primary"><a href="'.$this->url('catalogue', array(), array('query' => array('id'=>$plugin->getId()))).'">'.$plugin->getName().'</a></h4>
+            <p>ArtifactId: <b>'.$plugin->getArtifactId().'</b> &nbsp; &nbsp; <i class="fas fa-download"></i> '.number_format($plugin->getDownloads()).' <p>
+            <p>Author: <b>'.$plugin->getAuthorName().'</b></p> 
+            <p>License: <b>'.$plugin->getLicense().'</b></p> 
+            <p>'.implode('&nbsp;', $versionBadges).'</p>   
+        </td>
+        <td>';
+
+        foreach ($plugin->getCategories() as $cat) {
+            echo '<span class="badge badge-blue">'.$cat->getName().'</span> &nbsp;';
+        }    
+        
+        echo '</td><td>';
+        $a = array();
+        foreach ($plugin->getVersions() as $version) {
+            foreach ($version->getNbVersionsPluginVersions() as $nbvPv) {
+              $a[]=$nbvPv->getNbVersion()->getVersion();
+            }    
+          }
+        foreach (array_unique($a) as $nbvPv) {
+          echo '<span class="badge badge-brown">NB '.$nbvPv.'</span> &nbsp; ';
+        }
+        echo '</td>
+        <td>'.$plugin->getShortDescription().'</td>
+        </tr>';
+    }
+?>
+  </tbody>
+</table>
+<script type="text/javascript">
+  const searchElement = document.getElementById('search');
+  if (searchElement) {
+    searchElement.focus();
+    const val = searchElement.value; 
+    searchElement.value = '';
+    searchElement.value = val;
+  }
+  $( function() {
+    $( "#search" ).autocomplete({
+      source: "<?= $this->url('plugin',array('action'=>'search-autocomplete')) ?>",
+      minLength: 3,      
+    });
+  } );
+  </script>
+
+<?= $this->paginationControl($this->paginator,
+            'Sliding',
+            'partials/_paginator', 
+            ['route' => 'home', 'search' => $this->search]); ?>
diff --git a/pp3/module/Application/view/application/login/index.phtml b/pp3/module/Application/view/application/login/index.phtml
new file mode 100644
index 0000000..319bed5
--- /dev/null
+++ b/pp3/module/Application/view/application/login/index.phtml
@@ -0,0 +1,16 @@
+
+  <div class="row">
+    <div class="col-sm-3">
+      <form action="" method="post">
+        <div class="form-group">
+          <label for="exampleInputEmail1">Email</label>
+          <input type="email" class="form-control" id="email" aria-describedby="emailHelp" placeholder="Email">
+        </div>
+        <div class="form-group">
+          <label for="exampleInputPassword1">Heslo</label>
+          <input type="password" class="form-control" id="password" placeholder="Heslo">
+        </div>
+        <button type="submit" class="btn btn-primary">Přihlásit</button>
+      </form>
+    </div>   
+  </div>
diff --git a/pp3/module/Application/view/application/plugin-version/_pluginVersion-form.phtml b/pp3/module/Application/view/application/plugin-version/_pluginVersion-form.phtml
new file mode 100644
index 0000000..4833d41
--- /dev/null
+++ b/pp3/module/Application/view/application/plugin-version/_pluginVersion-form.phtml
@@ -0,0 +1,18 @@
+    <div class="form-group">
+        <label for="url">Url</label>
+        <input type="text" class="form-control" id="url" name="url" required placeholder="" value="<?= $this->pluginVersion->getUrl() ?>" readonly="true">
+    </div>
+    <div class="form-group">
+        <label for="version">Version</label>
+        <input type="text" class="form-control" id="version" name="version" placeholder="" value="<?= $this->pluginVersion->getVersion() ?>" readonly="true">
+    </div>
+    <div class="form-group">
+        <label for="relnotes">Release notes <span class="text-primary"></span></label>
+        <textarea class="form-control" id="relnotes" name="relnotes" rows="5"
+        placeholder="Release notes"><?= $this->pluginVersion->getRelnotes() ?></textarea>                
+    </div>
+    <div class="form-group">
+        <label for="url">NetBeans version</label>
+        <?= $this->partial('partials/_nbVersion-select.phtml', 
+                array('nbVersions' => $this->nbVersions, 'pluginVersion' =>$this->pluginVersion, 'verifiedNbVersionIds'=>$this->verifiedNbVersionIds)); ?>
+    </div>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/plugin-version/edit.phtml b/pp3/module/Application/view/application/plugin-version/edit.phtml
new file mode 100644
index 0000000..58f059d
--- /dev/null
+++ b/pp3/module/Application/view/application/plugin-version/edit.phtml
@@ -0,0 +1,16 @@
+<h3><span class="text-primary"><?= $this->pluginVersion->getPlugin()->getName()?> <?= $this->pluginVersion->getVersion()?></span> - version management</h3>
+    <div class="row">
+        <div class="col col-sm-6">
+            <?= $this->partial('layout/flash.phtml'); ?>
+            <form method="post" action="" class="needs-validation">
+            <?php 
+            echo $this->partial('application/plugin-version/_pluginVersion-form.phtml', 
+            array('pluginVersion' => $this->pluginVersion, 'nbVersions' => $this->nbVersions, 'verifiedNbVersionIds' => $this->verifiedNbVersionIds)); 
+            ?>
+            <a class="btn btn-secondary" href="../plugin/list" role="button">Return</a>
+            <button type="submit" class="btn btn-primary">Save Plugin Version</button>
+            </form>
+            
+        </div>
+    </div>
+    <br/>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/plugin/_plugin-form.phtml b/pp3/module/Application/view/application/plugin/_plugin-form.phtml
new file mode 100644
index 0000000..ea07e10
--- /dev/null
+++ b/pp3/module/Application/view/application/plugin/_plugin-form.phtml
@@ -0,0 +1,53 @@
+
+    <div class="form-group">
+        <label for="url">Author <span class="text-primary">*</span></label>
+        <input type="email" class="form-control" id="author" name="author" required placeholder="Author" value="<?= $this->plugin->getAuthor() ?>" xreadonly="true">
+    </div>
+    <div class="form-group">
+        <label for="urgroupIdl">GroupId</label>
+        <input type="text" class="form-control" id="groupId" name="groupid" placeholder="Enter groupId" value="<?= $this->plugin->getGroupId() ?>" readonly="true">
+    </div>
+    <div class="form-group">
+        <label for="url">ArtifactId</label>
+        <input type="text" class="form-control" id="artefictid" name="artifactid" placeholder="Enter artefactId" value="<?= $this->plugin->getArtifactId() ?>" readonly="true">
+    </div>
+    <div class="form-group">
+        <label for="url">URL</label>
+        <input type="text" class="form-control" id="url" name="url" placeholder="Enter url" value="<?= $this->plugin->getUrl() ?>" readonly="true">
+    </div>
+    <div class="form-group">
+        <label for="name">Name <span class="text-primary">*</span></label>
+        <input type="text" class="form-control" id="name" name="name" placeholder="Plugin name" value="<?= $this->plugin->getName() ?>" required>                
+    </div>
+    <div class="form-group">
+        <label for="name">License <span class="text-primary">*</span></label>
+        <input type="text" class="form-control" id="license" name="license" placeholder="License" value="<?= $this->plugin->getLicense() ?>" required>                
+    </div>
+    <div class="form-group">
+    <label for="cat1">Category #1</label>
+    <?= $this->partial('partials/_categories-select.phtml', array('fieldName' => 'category', 'categories' =>$this->categories, 'required' => true, 'selected' => $this->plugin->getCategories()[0])); ?>
+    </div>
+    <div class="form-group">
+    <label for="cat1">Category #2</label>
+    <?= $this->partial('partials/_categories-select.phtml', array('fieldName' => 'category2', 'categories' =>$this->categories, 'required' => false, 'selected' => $this->plugin->getCategories()[1])); ?>
+    </div>
+    <div class="form-group">
+        <label for="hp">Homepage</label>
+        <input type="text" class="form-control" id="hp" name="homepage" placeholder="Project homepage, github etc..." value="<?= $this->plugin->getHomepage() ?>">                
+    </div>
+    <div class="form-group">
+        <label for="sdescription">Short description <span class="text-primary">*</span></label>
+        <textarea class="form-control" id="sdescription" name="short_description" rows="5"
+        placeholder="Short description, few lines" required><?= $this->plugin->getShortDescription() ?></textarea>                
+        <p>Basic HTML syntax can be used for text formatting </p>
+    </div>
+    <div class="form-group">
+        <label for="description">Full description<span class="text-primary">*</span></label>
+        <textarea class="form-control" id="description" name="description" rows="7"
+        placeholder="Full, detail description" required><?= $this->plugin->getDescription() ?></textarea>                
+        <p>Basic HTML syntax can be used for text formatting </p>
+    </div>
+    <div class="form-group">
+        <label for="image-file">Image</label>
+        <input type="file" name="image-file" id="image-file">
+    </div>
diff --git a/pp3/module/Application/view/application/plugin/_plugin-listrow.phtml b/pp3/module/Application/view/application/plugin/_plugin-listrow.phtml
new file mode 100644
index 0000000..21d1cc4
--- /dev/null
+++ b/pp3/module/Application/view/application/plugin/_plugin-listrow.phtml
@@ -0,0 +1,76 @@
+<?php
+$pluugin = $this->plugin;
+echo '<tr>
+<td style="text-align: center;"><h4><i class="fas '.$plugin->getStatusIconClass().'" title="'.$plugin->getStatusTitle().'"></i></h4></td>
+<td>
+    <h4 class="text-primary">'.$plugin->getName().'</h4>
+    <p>
+        <a class="btn btn-default" href="'.$this->url('plugin',array('action'=>'edit'),array('query' => array('id'=>$plugin->getId()))).'" role="button" title="Edit">
+            <i class="fas fa-edit text-primary"></i>
+        </a>
+        <a class="btn btn-default" href="'.$this->url('plugin',array('action'=>'delete'),array('query' => array('id'=>$plugin->getId()))).'" role="button" title="Remove">
+            <i class="fas fa-trash text-danger"></i>
+        </a>
+        <a class="btn btn-default" href="'.$this->url('plugin',array('action'=>'sync'),array('query' => array('id'=>$plugin->getId()))).'" role="button" title="Sync with source manifest.">
+            <i class="fas fa-sync"></i>
+        </a>                
+    </p>
+    <p>Status: <b>'.$plugin->getStatusTitle().'</b></p>
+    <div>
+        <p>ArtifactId: <b>'.$plugin->getArtifactId().'</b><p>
+        <p>
+        <i class="fas fa-asterisk"></i> '.$plugin->getAddedAt()->format('Y-m-d').' &nbsp; &nbsp;
+        <i class="fas fa-edit"></i> '.$plugin->getLastUpdatedAt()->format('Y-m-d').' &nbsp; &nbsp; 
+        <i class="fas fa-download"></i> '.number_format($plugin->getDownloads()).' 
+        </p>                
+    </div>
+    <p>';
+
+foreach ($plugin->getCategories() as $cat) {
+    echo '<span class="badge badge-blue">'.$cat->getName().'</span> &nbsp;';
+}    
+
+echo '</p>
+</td>
+<td>
+    <table class="table table-striped">
+        <thead>
+            <tr>
+            <th scope="col" style="width: 170px;">Plugin Version</th>
+            <th scope="col" style="width: 100px;"></th>
+            <th scope="col">NB Versions</th>
+            <th scope="col">Verifications</th>
+            </tr>
+        </thead>
+        <tbody>';
+
+foreach ($plugin->getVersions() as $version) {
+    echo '<tr>
+        <td><span class="badge">'.$version->getVersion().'</span></td>
+        <td>
+            <a class="btn btn-default" href="'.$this->url('plugin-version',array('action'=>'edit'),array('query' => array('id'=>$version->getId()))).'" role="button" title="Edit">
+                <i class="fas fa-edit text-primary"></i>
+            </a>
+            <!-- <a class="btn btn-default" href="'.$this->url('plugin-version',array('action'=>'delete'),array('query' => array('id'=>$version->getId()))).'" role="button" title="Edit">
+                <i class="fas fa-trash text-danger"></i>
+            </a> -->
+        </td>
+        <td>';
+    foreach ($version->getNbVersionsPluginVersions() as $nbvPv) {
+            echo '<span class="badge badge-brown">NB '.$nbvPv->getNbVersion()->getVersion().'</span> &nbsp; ';
+    }    
+    echo '</td>
+        <td>';
+    foreach ($version->getNbVersionsPluginVersions() as $nbvPv) {
+        if ($nbvPv->getVerificationId()) {
+            echo '<span class="badge '.$nbvPv->getVerification()->getStatusBadgeClass().'" title="'.$nbvPv->getVerification()->getStatusBadgeTitle().'">
+            NB '.$nbvPv->getNbVersion()->getVersion().' - '.$nbvPv->getVerification()->getStatusBadgeTitle().'</span> &nbsp; ';
+        }
+    }
+    echo ' <td>
+    </tr>';
+}
+echo '</tbody>
+</table>
+</td>
+</tr>';
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/plugin/confirm.phtml b/pp3/module/Application/view/application/plugin/confirm.phtml
new file mode 100644
index 0000000..6c0c4c0
--- /dev/null
+++ b/pp3/module/Application/view/application/plugin/confirm.phtml
@@ -0,0 +1,12 @@
+<h3>Save Plugin</h3>
+    <div class="row">
+        <div class="col col-sm-6">
+            <?= $this->partial('layout/flash.phtml'); ?>
+            <form method="post" action="" class="needs-validation" enctype="multipart/form-data">
+            <?= $this->partial('application/plugin/_plugin-form.phtml', array('plugin' => $this->plugin, 'categories'=>$this->categories)); ?>
+            <a class="btn btn-secondary" href="../plugin/" role="button">Cancel</a>
+            <button type="submit" class="btn btn-primary">Save Plugin</button>
+            </form>
+            
+        </div>
+    </div>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/plugin/edit.phtml b/pp3/module/Application/view/application/plugin/edit.phtml
new file mode 100644
index 0000000..b42e29f
--- /dev/null
+++ b/pp3/module/Application/view/application/plugin/edit.phtml
@@ -0,0 +1,12 @@
+<h3>Edit Plugin</h3>
+    <div class="row">
+        <div class="col col-sm-6">
+            <?= $this->partial('layout/flash.phtml'); ?>
+            <form method="post" action="" class="needs-validation" enctype="multipart/form-data">
+            <?= $this->partial('application/plugin/_plugin-form.phtml', array('plugin' => $this->plugin, 'categories' => $this->categories)); ?>
+            <a class="btn btn-secondary" href="../plugin/list" role="button">Return</a>
+            <button type="submit" class="btn btn-primary">Save Plugin</button>
+            </form>
+            
+        </div>
+    </div>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/plugin/index.phtml b/pp3/module/Application/view/application/plugin/index.phtml
new file mode 100644
index 0000000..754fa12
--- /dev/null
+++ b/pp3/module/Application/view/application/plugin/index.phtml
@@ -0,0 +1,20 @@
+<h3>Add plugin</h3>
+    <div class="row">
+        <div class="col col-sm-6">
+            <?= $this->partial('layout/flash.phtml'); ?>
+            <form method="post" action="" enctype="multipart/form-data">
+            <div class="form-group">
+                <label>Plugin attributes from maven.org's <code>maven-metadata.xml</code> </label>
+            </div>
+            <div class="form-group">
+                <label for="urgroupIdl">GroupId</label>
+                <input type="text" class="form-control" id="groupId" name="groupid" placeholder="com.project" value="<?= $this->plugin->getGroupId() ?>" style="width: 400px;">
+            </div>
+            <div class="form-group">
+                <label for="url">ArtifactId</label>
+                <input type="text" class="form-control" id="artefictid" name="artifactid" placeholder="artifactId" value="<?= $this->plugin->getArtifactId() ?>" style="width: 400px;">
+            </div>
+            <button type="submit" class="btn btn-primary">Add Plugin</button>
+            </form>
+        </div>
+    </div>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/plugin/list.phtml b/pp3/module/Application/view/application/plugin/list.phtml
new file mode 100644
index 0000000..073f9af
--- /dev/null
+++ b/pp3/module/Application/view/application/plugin/list.phtml
@@ -0,0 +1,23 @@
+<h3>My plugins</h3>
+<div class="row">
+    <div class="col col-sm-6">
+        <?= $this->partial('layout/flash.phtml'); ?>
+    </div>
+</div>
+<?php
+if (empty($this->plugins)) {
+    echo '<p>You do not have any plugins yet.</p>';
+}
+?>
+<div class="row">
+<table class="table">
+    <tbody>
+    <?php
+    foreach($this->plugins as $plugin) {
+        echo $this->partial('application/plugin/_plugin-listrow.phtml', array('plugin' => $plugin));
+    }
+    ?>
+
+    </tbody>
+</table>
+</div>
\ No newline at end of file
diff --git a/pp3/module/Application/view/application/verification/list.phtml b/pp3/module/Application/view/application/verification/list.phtml
new file mode 100644
index 0000000..628f7ff
--- /dev/null
+++ b/pp3/module/Application/view/application/verification/list.phtml
@@ -0,0 +1,107 @@
+<h3>My verification requests</h3>
+<p>
+    Showing only your verification requests with yet undecided overal status.   
+</p>
+<?= $this->partial('layout/flash.phtml'); ?>
+<table class="table table-striped table-hover">
+    <thead>
+        <tr>
+            <th>Request for</th>
+            <th></th>
+            <th>Created</th>
+            <th>Overal status</th>
+            <th>My vote</th>
+            <th>Actions</th>
+        </tr>
+    </thead>
+    <tbody>
+<?php
+    foreach ($this->verificationRequests as $vReq) {
+        $verification = $vReq->getVerification();
+        $nbVersion = $verification->getNbVersionPluginVersion()->getNbVersion();
+        $pluginVersion = $vReq->getVerification()->getNbVersionPluginVersion()->getPluginVersion();
+        $plugin = $pluginVersion->getPlugin();
+        echo '<tr>
+        <td>
+            <span class="text text-primary" style="font-size:1.2em"><a href="'.$pluginVersion->getUrl().'">'.$plugin->getName().'</a></span>
+        </td>
+        <td>
+            <span class="badge">'.$pluginVersion->getVersion().'</span> &nbsp; <i class="fas fa-arrow-right"></i> &nbsp;
+            <span class="badge">NB '.$nbVersion->getVersion().'</span>
+        </td>
+        <td>'.$verification->getCreatedAt()->format('Y-m-d H:i').'</td>
+        <td>
+            <span class="badge '.$verification->getStatusBadgeClass().'" title="'.$verification->getStatusBadgeTitle().'">'.$verification->getStatusBadgeTitle().'</span>
+        </td>
+        <td>    
+            <span class="badge '.$vReq->getVoteBadgeClass().'" title="'.$vReq->getVoteBadgeTitle().'">'.$vReq->getVoteBadgeTitle().'</span>
+        </td>
+        <td>
+        <div>
+        <a href="'.$this->url('verification', array('action'=>'vote-go'), array('query' => array('id'=>$vReq->getId()))).'" class="btn btn-success" role="button">Go</a>
+        <a href="'.$this->url('verification', array('action'=>'vote-undecided'), array('query' => array('id'=>$vReq->getId()))).'" class="btn btn-default" role="button">Undecided</a>
+        <button type="button" class="btn btn-danger" role="button" data-toggle="modal" data-target="#noGoModal-'.$vReq->getId().'">NoGo</button>
+        
+        ';
+
+        // master options
+        if ($this->isAdmin) {
+            echo ' &nbsp; | &nbsp;
+            <a href="'.$this->url('verification', array('action'=>'vote-master-go'), array('query' => array('id'=>$verification->getId()))).'" class="btn btn-success" role="button">Master Go</a>        
+            <button type="button" class="btn btn-danger" role="button" data-toggle="modal" data-target="#masterNoGoModal-'.$verification->getId().'">Master NoGo</a>
+            ';
+        }
+        echo '
+        </div>
+        <div class="modal fade" id="noGoModal-'.$vReq->getId().'" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
+            <form action="'.$this->url('verification', array('action'=>'vote-nogo'), array('query' => array('id'=>$vReq->getId()))).'" method="post">
+                <div class="modal-dialog" role="document">
+                    <div class="modal-content">
+                    <div class="modal-header">
+                        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                        <h4 class="modal-title" id="myModalLabel">NoGo</h4>
+                    </div>
+                    <div class="modal-body">
+                        <div class="form-group">
+                            <label for="comment">NoGo Comment</label>
+                            <textarea class="form-control" id="comment" name="comment" rows="5"
+                            placeholder="Short description why giving NoGo"></textarea>                
+                        </div>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                        <button type="submit" class="btn btn-danger">NoGo</button>
+                    </div>
+                    </div>
+                </div>
+            </form>
+        </div>
+        <div class="modal fade" id="masterNoGoModal-'.$verification->getId().'" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
+            <form action="'.$this->url('verification', array('action'=>'vote-master-nogo'), array('query' => array('id'=>$verification->getId()))).'" method="post">
+                <div class="modal-dialog" role="document">
+                    <div class="modal-content">
+                    <div class="modal-header">
+                        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                        <h4 class="modal-title" id="myModalLabel">NoGo</h4>
+                    </div>
+                    <div class="modal-body">
+                        <div class="form-group">
+                            <label for="comment">NoGo Comment</label>
+                            <textarea class="form-control" id="comment" name="comment" rows="5"
+                            placeholder="Short description why giving NoGo"></textarea>                
+                        </div>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                        <button type="submit" class="btn btn-danger">NoGo</button>
+                    </div>
+                    </div>
+                </div>
+            </form>
+        </div>
+        </td>
+        </tr>';
+    }
+?>
+    </tbody>
+</table>
diff --git a/pp3/module/Application/view/error/404.phtml b/pp3/module/Application/view/error/404.phtml
new file mode 100755
index 0000000..765ce0b
--- /dev/null
+++ b/pp3/module/Application/view/error/404.phtml
@@ -0,0 +1,113 @@
+<h1><?php echo $this->translate('A 404 error occurred') ?></h1>
+<h2><?php echo $this->message ?></h2>
+
+<?php if (isset($this->reason) && $this->reason): ?>
+
+<?php
+$reasonMessage= '';
+switch ($this->reason) {
+    case 'error-controller-cannot-dispatch':
+        $reasonMessage = $this->translate('The requested controller was unable to dispatch the request.');
+        break;
+    case 'error-controller-not-found':
+        $reasonMessage = $this->translate('The requested controller could not be mapped to an existing controller class.');
+        break;
+    case 'error-controller-invalid':
+        $reasonMessage = $this->translate('The requested controller was not dispatchable.');
+        break;
+    case 'error-router-no-match':
+        $reasonMessage = $this->translate('The requested URL could not be matched by routing.');
+        break;
+    default:
+        $reasonMessage = $this->translate('We cannot determine at this time why a 404 was generated.');
+        break;
+}
+?>
+
+<p><?php echo $reasonMessage ?></p>
+
+<?php endif ?>
+
+<?php if (isset($this->controller) && $this->controller): ?>
+
+<dl>
+    <dt><?php echo $this->translate('Controller') ?>:</dt>
+    <dd><?php echo $this->escapeHtml($this->controller) ?>
+<?php
+if (isset($this->controller_class)
+    && $this->controller_class
+    && $this->controller_class != $this->controller
+) {
+    echo '(' . sprintf($this->translate('resolves to %s'), $this->escapeHtml($this->controller_class)) . ')';
+}
+?>
+</dd>
+</dl>
+
+<?php endif ?>
+
+<?php if (isset($this->display_exceptions) && $this->display_exceptions): ?>
+
+<?php if(isset($this->exception) && $this->exception instanceof Exception): ?>
+<hr/>
+<h2><?php echo $this->translate('Additional information') ?>:</h2>
+<h3><?php echo get_class($this->exception); ?></h3>
+<dl>
+    <dt><?php echo $this->translate('File') ?>:</dt>
+    <dd>
+        <pre class="prettyprint linenums"><?php echo $this->exception->getFile() ?>:<?php echo $this->exception->getLine() ?></pre>
+    </dd>
+    <dt><?php echo $this->translate('Message') ?>:</dt>
+    <dd>
+        <pre class="prettyprint linenums"><?php echo $this->exception->getMessage() ?></pre>
+    </dd>
+    <dt><?php echo $this->translate('Stack trace') ?>:</dt>
+    <dd>
+        <pre class="prettyprint linenums"><?php echo $this->exception->getTraceAsString() ?></pre>
+    </dd>
+</dl>
+<?php
+    $e = $this->exception->getPrevious();
+    $icount = 0;
+    if ($e) :
+?>
+<hr/>
+<h2><?php echo $this->translate('Previous exceptions') ?>:</h2>
+<ul class="unstyled">
+    <?php while($e) : ?>
+    <li>
+        <h3><?php echo get_class($e); ?></h3>
+        <dl>
+            <dt><?php echo $this->translate('File') ?>:</dt>
+            <dd>
+                <pre class="prettyprint linenums"><?php echo $e->getFile() ?>:<?php echo $e->getLine() ?></pre>
+            </dd>
+            <dt><?php echo $this->translate('Message') ?>:</dt>
+            <dd>
+                <pre class="prettyprint linenums"><?php echo $e->getMessage() ?></pre>
+            </dd>
+            <dt><?php echo $this->translate('Stack trace') ?>:</dt>
+            <dd>
+                <pre class="prettyprint linenums"><?php echo $e->getTraceAsString() ?></pre>
+            </dd>
+        </dl>
+    </li>
+    <?php
+        $e = $e->getPrevious();
+        $icount += 1;
+        if ($icount >=50) {
+            echo "<li>There may be more exceptions, but we have no enough memory to proccess it.</li>";
+            break;
+        }
+        endwhile;
+    ?>
+</ul>
+<?php endif; ?>
+
+<?php else: ?>
+
+<h3><?php echo $this->translate('No Exception available') ?></h3>
+
+<?php endif ?>
+
+<?php endif ?>
diff --git a/pp3/module/Application/view/error/index.phtml b/pp3/module/Application/view/error/index.phtml
new file mode 100755
index 0000000..ef5dad6
--- /dev/null
+++ b/pp3/module/Application/view/error/index.phtml
@@ -0,0 +1,68 @@
+<h1><?php echo $this->translate('An error occurred') ?></h1>
+<h2><?php echo $this->message ?></h2>
+
+<?php if (isset($this->display_exceptions) && $this->display_exceptions): ?>
+
+<?php if(isset($this->exception) && $this->exception instanceof Exception): ?>
+<hr/>
+<h2><?php echo $this->translate('Additional information') ?>:</h2>
+<h3><?php echo get_class($this->exception); ?></h3>
+<dl>
+    <dt><?php echo $this->translate('File') ?>:</dt>
+    <dd>
+        <pre class="prettyprint linenums"><?php echo $this->exception->getFile() ?>:<?php echo $this->exception->getLine() ?></pre>
+    </dd>
+    <dt><?php echo $this->translate('Message') ?>:</dt>
+    <dd>
+        <pre class="prettyprint linenums"><?php echo $this->escapeHtml($this->exception->getMessage()) ?></pre>
+    </dd>
+    <dt><?php echo $this->translate('Stack trace') ?>:</dt>
+    <dd>
+        <pre class="prettyprint linenums"><?php echo $this->escapeHtml($this->exception->getTraceAsString()) ?></pre>
+    </dd>
+</dl>
+<?php
+    $e = $this->exception->getPrevious();
+    $icount = 0;
+    if ($e) :
+?>
+<hr/>
+<h2><?php echo $this->translate('Previous exceptions') ?>:</h2>
+<ul class="unstyled">
+    <?php while($e) : ?>
+    <li>
+        <h3><?php echo get_class($e); ?></h3>
+        <dl>
+            <dt><?php echo $this->translate('File') ?>:</dt>
+            <dd>
+                <pre class="prettyprint linenums"><?php echo $e->getFile() ?>:<?php echo $e->getLine() ?></pre>
+            </dd>
+            <dt><?php echo $this->translate('Message') ?>:</dt>
+            <dd>
+                <pre class="prettyprint linenums"><?php echo $this->escapeHtml($e->getMessage()) ?></pre>
+            </dd>
+            <dt><?php echo $this->translate('Stack trace') ?>:</dt>
+            <dd>
+                <pre class="prettyprint linenums"><?php echo $this->escapeHtml($e->getTraceAsString()) ?></pre>
+            </dd>
+        </dl>
+    </li>
+    <?php
+        $e = $e->getPrevious();
+        $icount += 1;
+        if ($icount >= 50) {
+            echo "<li>There may be more exceptions, but we have no enough memory to proccess it.</li>";
+            break;
+        }
+        endwhile;
+    ?>
+</ul>
+<?php endif; ?>
+
+<?php else: ?>
+
+<h3><?php echo $this->translate('No Exception available') ?></h3>
+
+<?php endif ?>
+
+<?php endif ?>
diff --git a/pp3/module/Application/view/layout/flash.phtml b/pp3/module/Application/view/layout/flash.phtml
new file mode 100644
index 0000000..00df6f2
--- /dev/null
+++ b/pp3/module/Application/view/layout/flash.phtml
@@ -0,0 +1,13 @@
+<?php
+$flash = $this->flashMessenger();
+$flash->setAutoEscape(false);
+$flash->setMessageOpenFormat('<div%s>
+<button type="button" class="close" data-dismiss="alert" aria-hidden="true">
+    &times;
+</button>
+<div>')->setMessageCloseString('</div></div>');
+echo $flash->renderCurrent('error', array('alert', 'alert-dismissable', 'alert-danger'));
+echo $flash->renderCurrent('info', array('alert', 'alert-dismissable', 'alert-info'));
+echo $flash->renderCurrent('default', array('alert', 'alert-dismissable', 'alert-info'));
+echo $flash->renderCurrent('success', array('alert', 'alert-dismissable', 'alert-success'));
+?>
\ No newline at end of file
diff --git a/pp3/module/Application/view/layout/layout.phtml b/pp3/module/Application/view/layout/layout.phtml
new file mode 100755
index 0000000..3bef292
--- /dev/null
+++ b/pp3/module/Application/view/layout/layout.phtml
@@ -0,0 +1,111 @@
+<?php echo $this->doctype(); ?>
+
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <meta name="google-signin-client_id" content="432862904114-ierlf9j6qmmuhtd44ecmlfqivlirq7uc.apps.googleusercontent.com">
+        <?php echo $this->headTitle('Apache NetBeans Plugin Portal ') ?>
+
+        <?php
+        echo $this->headMeta()
+                ->appendName('viewport', 'width=device-width, initial-scale=1.0')
+                ->appendHttpEquiv('X-UA-Compatible', 'IE=edge')
+        ?>
+
+        <!-- Le styles -->
+        <?php
+        echo $this->headLink()
+                ->prependStylesheet($this->basePath('scss/style.css'))
+                //->prependStylesheet($this->basePath('js/datepicker/css/bootstrap-datepicker3.min.css'))
+                ->prependStylesheet($this->basePath('css/bootstrap-theme.min.css'))
+                ->prependStylesheet($this->basePath('css/bootstrap.min.css'))
+                //->prependStylesheet($this->basePath('css/font-awesome.min.css'))
+        ?>
+        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
+        <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+
+        <!-- Scripts -->
+        <?php
+        echo $this->headScript()
+                ->prependFile($this->basePath('js/script.js'))
+                //->prependFile($this->basePath('js/datepicker/js/bootstrap-datepicker.min.js'))
+                //->prependFile($this->basePath('js/tinymce/tinymce.min.js'))
+                ->prependFile($this->basePath('js/jquery.ba-throttle-debounce.min.js'))
+                ->prependFile($this->basePath('js/validator.min.js'))
+                ->prependFile($this->basePath('js/bootstrap.min.js'))
+                ->prependFile('//code.jquery.com/ui/1.12.1/jquery-ui.min.js')
+                ->prependFile($this->basePath('js/jquery.min.js'))
+                ->prependFile($this->basePath('js/respond.min.js'), 'text/javascript',
+                        array('conditional' => 'lt IE 9',))
+                ->prependFile($this->basePath('js/html5shiv.min.js'), 'text/javascript',
+                        array('conditional' => 'lt IE 9',))
+        ;
+        ?>
+        <script src="https://apis.google.com/js/platform.js?onload=onLoad" async defer></script>
+        <script type="text/javascript">
+            const BASE_URL = '<?= $this->url('home')?>';
+        </script>   
+    </head>
+    <body>
+        <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation" id="pp-navbar">
+            <div class="container-fluid">
+                <div class="navbar-header">
+                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+                        <span class="icon-bar"></span>
+                        <span class="icon-bar"></span>
+                        <span class="icon-bar"></span>
+                    </button>
+                    <a class="navbar-brand" href="<?= $this->url('home') ?>">
+                    <img src="<?= $this->basePath('img/apache-netbeans.svg')?>" style="padding-right: 8px; height: 30px;">
+                    <span class="r-white">Apache NetBeans Plugin Portal</span></a>
+                </div>
+                <div class="collapse navbar-collapse">
+                    <ul class="nav navbar-nav" id="mynav">
+                        <li><a href="<?= $this->url('home') ?>">Plugin Catalog</a></li>
+                        <?php if ($_SESSION['sessionUserId']) { ?>
+                        <li><a href="<?= $this->url('plugin') ?>">Add plugin</a></li>
+                        <li ><a href="<?= $this->url('plugin', array('action' => 'list'))?>">My plugins</a></li>
+                        
+                        <?php
+                            if ($_SESSION['isVerifier']) {
+                                echo '<li><a href="'.$this->url('verification', array('action' => 'list')).'">Verification requests</a></li>';
+                            }
+                            ?>
+                            <?php } ?>
+                            <?php
+                        if ($_SESSION['isAdmin']) {
+                            echo '<li><a href="'.$this->url('admin').'">Admin</a></li>';
+                        }
+                        ?>
+                        <li><a href="https://cwiki.apache.org/confluence/display/NETBEANS/How+to+get+plugin+on+Plugin+Portal+Update+Center">Help</a></li>
+                    </ul>
+                    <div class="pull-right">
+                        <div style="margin: 7px 20px;">
+                        <?php                        
+                            if (!$_SESSION['sessionUserId']) {                            
+                                echo '<div class="g-signin2" data-onsuccess="onSignIn" approvalprompt="force" ></div>';
+                            } else {
+                                echo '<div style = "display:none" align="middle" class="g-signin2" data-cookiepolicy=\'single_host_origin\' data-onsuccess="onSignIn"></div>';
+                                echo '<a href="#" onclick="signOut();" class="btn btn-default" role="button">Sign out '.$_SESSION['sessionUserId'].'</a>';
+                                // echo '<span class="badge" style="display:inline-block;margin-top: 10px;">'.$_SESSION['sessionUserId'].'</a>';
+                            }
+                        ?>
+                        </div>
+                    </div>
+                </div><!--/.nav-collapse -->
+               
+            </div>
+        </nav>
+        <div class="container-fluid" style="margin: 0px 30px;">
+            <div class="r-pad">
+                <?php                 
+                echo $this->content; 
+                ?>
+            </div>
+            <footer class='pp-footer'>
+            Apache NetBeans Plugin Portal, build #191001
+            </footer>
+        </div> <!-- /container -->
+        <?php echo $this->inlineScript() ?>
+    </body>
+</html>
diff --git a/pp3/module/Application/view/partials/_categories-select.phtml b/pp3/module/Application/view/partials/_categories-select.phtml
new file mode 100644
index 0000000..758495e
--- /dev/null
+++ b/pp3/module/Application/view/partials/_categories-select.phtml
@@ -0,0 +1,11 @@
+<select name="<?= $this->fieldName?>" class="form-control" <?= $this->required ? 'required' : ''?> >
+<option>Select category</option>
+<?php
+foreach ($this->categories as $cat) {
+    if ($this->selected) {
+        $sel = $cat->getId() == $this->selected->getId() ? 'selected' : '';
+    }
+    echo '<option value="'.$cat->getId().'" '.$sel.'>'.$cat->getName().'</option>';
+}
+?>
+</select>
\ No newline at end of file
diff --git a/pp3/module/Application/view/partials/_nbVersion-select.phtml b/pp3/module/Application/view/partials/_nbVersion-select.phtml
new file mode 100644
index 0000000..b442aca
--- /dev/null
+++ b/pp3/module/Application/view/partials/_nbVersion-select.phtml
@@ -0,0 +1,36 @@
+<?php
+$mapping = array();
+foreach($this->pluginVersion->getNbVersionsPluginVersions() as $nbvPv) {
+    $assignedNbVersions[$nbvPv->getNbVersionId()] = $nbvPv;    
+}
+if($this->nbVersions) {
+    echo '<table class="table table-striped">';
+    foreach ($this->nbVersions as $nbv) {  
+        echo '            
+        <tr>
+        <td>
+        <div class="checkbox">
+            <label>
+                <input type="checkbox" value="'.$nbv->getId().'" name="nbVersion_ids[]" '.(array_key_exists($nbv->getId(), $assignedNbVersions) ? 'checked' : '').'>    
+                <span class="badge badge-brown">NB '.$nbv->getVersion().'</span>          
+            </label>
+        </div>
+        <td>
+        <td>';
+        if (array_key_exists($nbv->getId(), $assignedNbVersions)) {
+            $nbvPv = $assignedNbVersions[$nbv->getId()];
+            if ($nbvPv->getVerificationId()) {
+                echo 'Verification request created on '.$nbvPv->getVerification()->getCreatedAt()->format('Y-m-d').' 
+                &nbsp; &nbsp; <span class="badge '.$nbvPv->getVerification()->getStatusBadgeClass().'">'.$nbvPv->getVerification()->getStatusBadgeTitle().'</span>
+                &nbsp;&nbsp;
+                <a href="'.$this->url('plugin-version',array('action'=>'edit'),array('query' => array('id' => $this->pluginVersion->getId(), 'verifId' => $nbvPv->getVerification()->getId()))).'" class="btn btn-default" role="button">Drop verification</a>';
+            } elseif(!in_array($nbv->getId(), $this->verifiedNbVersionIds)) {
+                echo '<a href="'.$this->url('verification',array('action'=>'create'),array('query' => array('nbvPvId' => $nbvPv->getId()))).'" class="btn btn-default" role="button">Request verification</a>';
+            }
+        }
+
+        echo '</td>
+        </tr>';
+    }    
+    echo '</table>';
+}
\ No newline at end of file
diff --git a/pp3/module/Application/view/partials/_paginator.phtml b/pp3/module/Application/view/partials/_paginator.phtml
new file mode 100644
index 0000000..30e1034
--- /dev/null
+++ b/pp3/module/Application/view/partials/_paginator.phtml
@@ -0,0 +1,46 @@
+<?php if ($this->pageCount): ?>
+
+<nav>
+<ul class="pagination">
+
+<!-- Previous page link -->
+<?php if (isset($this->previous)): ?>
+    <li>
+      <a href="<?= $this->url($this->route, [], ['query'=>['page'=>$this->previous, 'search'=>$this->search]]); ?>" aria-label="Previous">
+        <span aria-hidden="true">&laquo;</span>
+      </a>
+    </li>  
+<?php else: ?>
+    <li>
+        <span aria-hidden="true">&laquo;</span>      
+    </li>  
+<?php endif; ?>
+
+<!-- Numbered page links -->
+<?php foreach ($this->pagesInRange as $page): ?>
+  <?php if ($page != $this->current): ?>
+    <li>
+        <a href="<?= $this->url($this->route, [], ['query'=>['page'=>$page, 'search'=>$this->search]]); ?>"><?= $this->escapeHtml($page); ?></a>
+    </li>    
+  <?php else: ?>
+    <li>
+        <span aria-hidden="true"><b><?= $this->escapeHtml($page); ?></b></span> 
+    </li>    
+  <?php endif; ?>
+<?php endforeach; ?>
+
+<!-- Next page link -->
+<?php if (isset($this->next)): ?>
+    <li>
+      <a href="<?php echo $this->url($this->route, [], ['query'=>['page'=>$this->next, 'search'=>$this->search]]); ?>" aria-label="Next">
+        <span aria-hidden="true">&raquo;</span>
+      </a>
+    </li>  
+<?php else: ?>
+    <li>
+        <span aria-hidden="true">&raquo;</span>      
+    </li> 
+<?php endif; ?>
+</ul>
+</nav>
+<?php endif; ?>
\ No newline at end of file
diff --git a/pp3/public/.htaccess b/pp3/public/.htaccess
new file mode 100755
index 0000000..de2cf3f
--- /dev/null
+++ b/pp3/public/.htaccess
@@ -0,0 +1,16 @@
+RewriteEngine On
+# The following rule tells Apache that if the requested filename
+# exists, simply serve it.
+RewriteCond %{REQUEST_FILENAME} -s [OR]
+RewriteCond %{REQUEST_FILENAME} -l [OR]
+RewriteCond %{REQUEST_FILENAME} -d
+RewriteRule ^.*$ - [NC,L]
+# The following rewrites all other queries to index.php. The 
+# condition ensures that if you are using Apache aliases to do
+# mass virtual hosting, the base path will be prepended to 
+# allow proper resolution of the index.php file; it will work
+# in non-aliased environments as well, providing a safe, one-size 
+# fits all solution.
+RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
+RewriteRule ^(.*) - [E=BASE:%1]
+RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]
diff --git a/pp3/public/css/bootstrap-theme.css b/pp3/public/css/bootstrap-theme.css
new file mode 100755
index 0000000..df2d3d9
--- /dev/null
+++ b/pp3/public/css/bootstrap-theme.css
@@ -0,0 +1,397 @@
+/*!
+ * Bootstrap v3.0.3 (http://getbootstrap.com)
+ * Copyright 2013 Twitter, Inc.
+ * Licensed under http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+.btn-default,
+.btn-primary,
+.btn-success,
+.btn-info,
+.btn-warning,
+.btn-danger {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.btn-default:active,
+.btn-primary:active,
+.btn-success:active,
+.btn-info:active,
+.btn-warning:active,
+.btn-danger:active,
+.btn-default.active,
+.btn-primary.active,
+.btn-success.active,
+.btn-info.active,
+.btn-warning.active,
+.btn-danger.active {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+
+.btn:active,
+.btn.active {
+  background-image: none;
+}
+
+.btn-default {
+  text-shadow: 0 1px 0 #fff;
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);
+  background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);
+  background-repeat: repeat-x;
+  border-color: #dbdbdb;
+  border-color: #ccc;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-default:hover,
+.btn-default:focus {
+  background-color: #e0e0e0;
+  background-position: 0 -15px;
+}
+
+.btn-default:active,
+.btn-default.active {
+  background-color: #e0e0e0;
+  border-color: #dbdbdb;
+}
+
+.btn-primary {
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
+  background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
+  background-repeat: repeat-x;
+  border-color: #2b669a;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-primary:hover,
+.btn-primary:focus {
+  background-color: #2d6ca2;
+  background-position: 0 -15px;
+}
+
+.btn-primary:active,
+.btn-primary.active {
+  background-color: #2d6ca2;
+  border-color: #2b669a;
+}
+
+.btn-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
+  background-repeat: repeat-x;
+  border-color: #3e8f3e;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-success:hover,
+.btn-success:focus {
+  background-color: #419641;
+  background-position: 0 -15px;
+}
+
+.btn-success:active,
+.btn-success.active {
+  background-color: #419641;
+  border-color: #3e8f3e;
+}
+
+.btn-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
+  background-repeat: repeat-x;
+  border-color: #e38d13;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-warning:hover,
+.btn-warning:focus {
+  background-color: #eb9316;
+  background-position: 0 -15px;
+}
+
+.btn-warning:active,
+.btn-warning.active {
+  background-color: #eb9316;
+  border-color: #e38d13;
+}
+
+.btn-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
+  background-repeat: repeat-x;
+  border-color: #b92c28;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-danger:hover,
+.btn-danger:focus {
+  background-color: #c12e2a;
+  background-position: 0 -15px;
+}
+
+.btn-danger:active,
+.btn-danger.active {
+  background-color: #c12e2a;
+  border-color: #b92c28;
+}
+
+.btn-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
+  background-repeat: repeat-x;
+  border-color: #28a4c9;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-info:hover,
+.btn-info:focus {
+  background-color: #2aabd2;
+  background-position: 0 -15px;
+}
+
+.btn-info:active,
+.btn-info.active {
+  background-color: #2aabd2;
+  border-color: #28a4c9;
+}
+
+.thumbnail,
+.img-thumbnail {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
+}
+
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  background-color: #e8e8e8;
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+}
+
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  background-color: #357ebd;
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
+}
+
+.navbar-default {
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
+  background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
+  background-repeat: repeat-x;
+  border-radius: 4px;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
+}
+
+.navbar-default .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
+  background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
+}
+
+.navbar-brand,
+.navbar-nav > li > a {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
+}
+
+.navbar-inverse {
+  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);
+  background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.navbar-inverse .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #222222 0%, #282828 100%);
+  background-image: linear-gradient(to bottom, #222222 0%, #282828 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
+}
+
+.navbar-inverse .navbar-brand,
+.navbar-inverse .navbar-nav > li > a {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.navbar-static-top,
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  border-radius: 0;
+}
+
+.alert {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.alert-success {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
+  background-repeat: repeat-x;
+  border-color: #b2dba1;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
+}
+
+.alert-info {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
+  background-repeat: repeat-x;
+  border-color: #9acfea;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
+}
+
+.alert-warning {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
+  background-repeat: repeat-x;
+  border-color: #f5e79e;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
+}
+
+.alert-danger {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
+  background-repeat: repeat-x;
+  border-color: #dca7a7;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
+}
+
+.progress {
+  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
+}
+
+.progress-bar {
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
+  background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
+}
+
+.progress-bar-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
+}
+
+.progress-bar-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
+}
+
+.progress-bar-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
+}
+
+.progress-bar-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
+}
+
+.list-group {
+  border-radius: 4px;
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
+}
+
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  text-shadow: 0 -1px 0 #3071a9;
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
+  background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
+  background-repeat: repeat-x;
+  border-color: #3278b3;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
+}
+
+.panel {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.panel-default > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+}
+
+.panel-primary > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
+  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
+}
+
+.panel-success > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
+}
+
+.panel-info > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
+}
+
+.panel-warning > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
+}
+
+.panel-danger > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
+}
+
+.well {
+  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
+  background-repeat: repeat-x;
+  border-color: #dcdcdc;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
+  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
+          box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
+}
\ No newline at end of file
diff --git a/pp3/public/css/bootstrap-theme.min.css b/pp3/public/css/bootstrap-theme.min.css
new file mode 100755
index 0000000..c7b6d39
--- /dev/null
+++ b/pp3/public/css/bootstrap-theme.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v3.0.3 (http://getbootstrap.com)
+ * Copyright 2013 Twitter, Inc.
+ * Licensed under http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-dan [...]
\ No newline at end of file
diff --git a/pp3/public/css/bootstrap.css b/pp3/public/css/bootstrap.css
new file mode 100755
index 0000000..377dff3
--- /dev/null
+++ b/pp3/public/css/bootstrap.css
@@ -0,0 +1,7118 @@
+/*!
+ * Bootstrap v3.0.3 (http://getbootstrap.com)
+ * Copyright 2013 Twitter, Inc.
+ * Licensed under http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section,
+summary {
+  display: block;
+}
+
+audio,
+canvas,
+video {
+  display: inline-block;
+}
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+[hidden],
+template {
+  display: none;
+}
+
+html {
+  font-family: sans-serif;
+  -webkit-text-size-adjust: 100%;
+      -ms-text-size-adjust: 100%;
+}
+
+body {
+  margin: 0;
+}
+
+a {
+  background: transparent;
+}
+
+a:focus {
+  outline: thin dotted;
+}
+
+a:active,
+a:hover {
+  outline: 0;
+}
+
+h1 {
+  margin: 0.67em 0;
+  font-size: 2em;
+}
+
+abbr[title] {
+  border-bottom: 1px dotted;
+}
+
+b,
+strong {
+  font-weight: bold;
+}
+
+dfn {
+  font-style: italic;
+}
+
+hr {
+  height: 0;
+  -moz-box-sizing: content-box;
+       box-sizing: content-box;
+}
+
+mark {
+  color: #000;
+  background: #ff0;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, serif;
+  font-size: 1em;
+}
+
+pre {
+  white-space: pre-wrap;
+}
+
+q {
+  quotes: "\201C" "\201D" "\2018" "\2019";
+}
+
+small {
+  font-size: 80%;
+}
+
+sub,
+sup {
+  position: relative;
+  font-size: 75%;
+  line-height: 0;
+  vertical-align: baseline;
+}
+
+sup {
+  top: -0.5em;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+img {
+  border: 0;
+}
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+figure {
+  margin: 0;
+}
+
+fieldset {
+  padding: 0.35em 0.625em 0.75em;
+  margin: 0 2px;
+  border: 1px solid #c0c0c0;
+}
+
+legend {
+  padding: 0;
+  border: 0;
+}
+
+button,
+input,
+select,
+textarea {
+  margin: 0;
+  font-family: inherit;
+  font-size: 100%;
+}
+
+button,
+input {
+  line-height: normal;
+}
+
+button,
+select {
+  text-transform: none;
+}
+
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+  cursor: pointer;
+  -webkit-appearance: button;
+}
+
+button[disabled],
+html input[disabled] {
+  cursor: default;
+}
+
+input[type="checkbox"],
+input[type="radio"] {
+  padding: 0;
+  box-sizing: border-box;
+}
+
+input[type="search"] {
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+  -webkit-appearance: textfield;
+}
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+textarea {
+  overflow: auto;
+  vertical-align: top;
+}
+
+table {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+@media print {
+  * {
+    color: #000 !important;
+    text-shadow: none !important;
+    background: transparent !important;
+    box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  a[href]:after {
+    content: " (" attr(href) ")";
+  }
+  abbr[title]:after {
+    content: " (" attr(title) ")";
+  }
+  a[href^="javascript:"]:after,
+  a[href^="#"]:after {
+    content: "";
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  img {
+    max-width: 100% !important;
+  }
+  @page  {
+    margin: 2cm .5cm;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  select {
+    background: #fff !important;
+  }
+  .navbar {
+    display: none;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .btn > .caret,
+  .dropup > .btn > .caret {
+    border-top-color: #000 !important;
+  }
+  .label {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #ddd !important;
+  }
+}
+
+*,
+*:before,
+*:after {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+html {
+  font-size: 62.5%;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+body {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  line-height: 1.428571429;
+  color: #333333;
+  background-color: #ffffff;
+}
+
+input,
+button,
+select,
+textarea {
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit;
+}
+
+a {
+  color: #428bca;
+  text-decoration: none;
+}
+
+a:hover,
+a:focus {
+  color: #2a6496;
+  text-decoration: underline;
+}
+
+a:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+img {
+  vertical-align: middle;
+}
+
+.img-responsive {
+  display: block;
+  height: auto;
+  max-width: 100%;
+}
+
+.img-rounded {
+  border-radius: 6px;
+}
+
+.img-thumbnail {
+  display: inline-block;
+  height: auto;
+  max-width: 100%;
+  padding: 4px;
+  line-height: 1.428571429;
+  background-color: #ffffff;
+  border: 1px solid #dddddd;
+  border-radius: 4px;
+  -webkit-transition: all 0.2s ease-in-out;
+          transition: all 0.2s ease-in-out;
+}
+
+.img-circle {
+  border-radius: 50%;
+}
+
+hr {
+  margin-top: 20px;
+  margin-bottom: 20px;
+  border: 0;
+  border-top: 1px solid #eeeeee;
+}
+
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small,
+.h1 small,
+.h2 small,
+.h3 small,
+.h4 small,
+.h5 small,
+.h6 small,
+h1 .small,
+h2 .small,
+h3 .small,
+h4 .small,
+h5 .small,
+h6 .small,
+.h1 .small,
+.h2 .small,
+.h3 .small,
+.h4 .small,
+.h5 .small,
+.h6 .small {
+  font-weight: normal;
+  line-height: 1;
+  color: #999999;
+}
+
+h1,
+h2,
+h3 {
+  margin-top: 20px;
+  margin-bottom: 10px;
+}
+
+h1 small,
+h2 small,
+h3 small,
+h1 .small,
+h2 .small,
+h3 .small {
+  font-size: 65%;
+}
+
+h4,
+h5,
+h6 {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+
+h4 small,
+h5 small,
+h6 small,
+h4 .small,
+h5 .small,
+h6 .small {
+  font-size: 75%;
+}
+
+h1,
+.h1 {
+  font-size: 36px;
+}
+
+h2,
+.h2 {
+  font-size: 30px;
+}
+
+h3,
+.h3 {
+  font-size: 24px;
+}
+
+h4,
+.h4 {
+  font-size: 18px;
+}
+
+h5,
+.h5 {
+  font-size: 14px;
+}
+
+h6,
+.h6 {
+  font-size: 12px;
+}
+
+p {
+  margin: 0 0 10px;
+}
+
+.lead {
+  margin-bottom: 20px;
+  font-size: 16px;
+  font-weight: 200;
+  line-height: 1.4;
+}
+
+@media (min-width: 768px) {
+  .lead {
+    font-size: 21px;
+  }
+}
+
+small,
+.small {
+  font-size: 85%;
+}
+
+cite {
+  font-style: normal;
+}
+
+.text-muted {
+  color: #999999;
+}
+
+.text-primary {
+  color: #428bca;
+}
+
+.text-primary:hover {
+  color: #3071a9;
+}
+
+.text-warning {
+  color: #8a6d3b;
+}
+
+.text-warning:hover {
+  color: #66512c;
+}
+
+.text-danger {
+  color: #a94442;
+}
+
+.text-danger:hover {
+  color: #843534;
+}
+
+.text-success {
+  color: #3c763d;
+}
+
+.text-success:hover {
+  color: #2b542c;
+}
+
+.text-info {
+  color: #31708f;
+}
+
+.text-info:hover {
+  color: #245269;
+}
+
+.text-left {
+  text-align: left;
+}
+
+.text-right {
+  text-align: right;
+}
+
+.text-center {
+  text-align: center;
+}
+
+.page-header {
+  padding-bottom: 9px;
+  margin: 40px 0 20px;
+  border-bottom: 1px solid #eeeeee;
+}
+
+ul,
+ol {
+  margin-top: 0;
+  margin-bottom: 10px;
+}
+
+ul ul,
+ol ul,
+ul ol,
+ol ol {
+  margin-bottom: 0;
+}
+
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline > li {
+  display: inline-block;
+  padding-right: 5px;
+  padding-left: 5px;
+}
+
+.list-inline > li:first-child {
+  padding-left: 0;
+}
+
+dl {
+  margin-top: 0;
+  margin-bottom: 20px;
+}
+
+dt,
+dd {
+  line-height: 1.428571429;
+}
+
+dt {
+  font-weight: bold;
+}
+
+dd {
+  margin-left: 0;
+}
+
+@media (min-width: 768px) {
+  .dl-horizontal dt {
+    float: left;
+    width: 160px;
+    overflow: hidden;
+    clear: left;
+    text-align: right;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .dl-horizontal dd {
+    margin-left: 180px;
+  }
+  .dl-horizontal dd:before,
+  .dl-horizontal dd:after {
+    display: table;
+    content: " ";
+  }
+  .dl-horizontal dd:after {
+    clear: both;
+  }
+  .dl-horizontal dd:before,
+  .dl-horizontal dd:after {
+    display: table;
+    content: " ";
+  }
+  .dl-horizontal dd:after {
+    clear: both;
+  }
+}
+
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #999999;
+}
+
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+blockquote {
+  padding: 10px 20px;
+  margin: 0 0 20px;
+  border-left: 5px solid #eeeeee;
+}
+
+blockquote p {
+  font-size: 17.5px;
+  font-weight: 300;
+  line-height: 1.25;
+}
+
+blockquote p:last-child {
+  margin-bottom: 0;
+}
+
+blockquote small,
+blockquote .small {
+  display: block;
+  line-height: 1.428571429;
+  color: #999999;
+}
+
+blockquote small:before,
+blockquote .small:before {
+  content: '\2014 \00A0';
+}
+
+blockquote.pull-right {
+  padding-right: 15px;
+  padding-left: 0;
+  border-right: 5px solid #eeeeee;
+  border-left: 0;
+}
+
+blockquote.pull-right p,
+blockquote.pull-right small,
+blockquote.pull-right .small {
+  text-align: right;
+}
+
+blockquote.pull-right small:before,
+blockquote.pull-right .small:before {
+  content: '';
+}
+
+blockquote.pull-right small:after,
+blockquote.pull-right .small:after {
+  content: '\00A0 \2014';
+}
+
+blockquote:before,
+blockquote:after {
+  content: "";
+}
+
+address {
+  margin-bottom: 20px;
+  font-style: normal;
+  line-height: 1.428571429;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+
+code {
+  padding: 2px 4px;
+  font-size: 90%;
+  color: #c7254e;
+  white-space: nowrap;
+  background-color: #f9f2f4;
+  border-radius: 4px;
+}
+
+pre {
+  display: block;
+  padding: 9.5px;
+  margin: 0 0 10px;
+  font-size: 13px;
+  line-height: 1.428571429;
+  color: #333333;
+  word-break: break-all;
+  word-wrap: break-word;
+  background-color: #f5f5f5;
+  border: 1px solid #cccccc;
+  border-radius: 4px;
+}
+
+pre code {
+  padding: 0;
+  font-size: inherit;
+  color: inherit;
+  white-space: pre-wrap;
+  background-color: transparent;
+  border-radius: 0;
+}
+
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+
+.container {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-right: auto;
+  margin-left: auto;
+}
+
+.container:before,
+.container:after {
+  display: table;
+  content: " ";
+}
+
+.container:after {
+  clear: both;
+}
+
+.container:before,
+.container:after {
+  display: table;
+  content: " ";
+}
+
+.container:after {
+  clear: both;
+}
+
+@media (min-width: 768px) {
+  .container {
+    width: 750px;
+  }
+}
+
+@media (min-width: 992px) {
+  .container {
+    width: 970px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .container {
+    width: 1170px;
+  }
+}
+
+.row {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+
+.row:before,
+.row:after {
+  display: table;
+  content: " ";
+}
+
+.row:after {
+  clear: both;
+}
+
+.row:before,
+.row:after {
+  display: table;
+  content: " ";
+}
+
+.row:after {
+  clear: both;
+}
+
+.col-xs-1,
+.col-sm-1,
+.col-md-1,
+.col-lg-1,
+.col-xs-2,
+.col-sm-2,
+.col-md-2,
+.col-lg-2,
+.col-xs-3,
+.col-sm-3,
+.col-md-3,
+.col-lg-3,
+.col-xs-4,
+.col-sm-4,
+.col-md-4,
+.col-lg-4,
+.col-xs-5,
+.col-sm-5,
+.col-md-5,
+.col-lg-5,
+.col-xs-6,
+.col-sm-6,
+.col-md-6,
+.col-lg-6,
+.col-xs-7,
+.col-sm-7,
+.col-md-7,
+.col-lg-7,
+.col-xs-8,
+.col-sm-8,
+.col-md-8,
+.col-lg-8,
+.col-xs-9,
+.col-sm-9,
+.col-md-9,
+.col-lg-9,
+.col-xs-10,
+.col-sm-10,
+.col-md-10,
+.col-lg-10,
+.col-xs-11,
+.col-sm-11,
+.col-md-11,
+.col-lg-11,
+.col-xs-12,
+.col-sm-12,
+.col-md-12,
+.col-lg-12 {
+  position: relative;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+
+.col-xs-1,
+.col-xs-2,
+.col-xs-3,
+.col-xs-4,
+.col-xs-5,
+.col-xs-6,
+.col-xs-7,
+.col-xs-8,
+.col-xs-9,
+.col-xs-10,
+.col-xs-11,
+.col-xs-12 {
+  float: left;
+}
+
+.col-xs-12 {
+  width: 100%;
+}
+
+.col-xs-11 {
+  width: 91.66666666666666%;
+}
+
+.col-xs-10 {
+  width: 83.33333333333334%;
+}
+
+.col-xs-9 {
+  width: 75%;
+}
+
+.col-xs-8 {
+  width: 66.66666666666666%;
+}
+
+.col-xs-7 {
+  width: 58.333333333333336%;
+}
+
+.col-xs-6 {
+  width: 50%;
+}
+
+.col-xs-5 {
+  width: 41.66666666666667%;
+}
+
+.col-xs-4 {
+  width: 33.33333333333333%;
+}
+
+.col-xs-3 {
+  width: 25%;
+}
+
+.col-xs-2 {
+  width: 16.666666666666664%;
+}
+
+.col-xs-1 {
+  width: 8.333333333333332%;
+}
+
+.col-xs-pull-12 {
+  right: 100%;
+}
+
+.col-xs-pull-11 {
+  right: 91.66666666666666%;
+}
+
+.col-xs-pull-10 {
+  right: 83.33333333333334%;
+}
+
+.col-xs-pull-9 {
+  right: 75%;
+}
+
+.col-xs-pull-8 {
+  right: 66.66666666666666%;
+}
+
+.col-xs-pull-7 {
+  right: 58.333333333333336%;
+}
+
+.col-xs-pull-6 {
+  right: 50%;
+}
+
+.col-xs-pull-5 {
+  right: 41.66666666666667%;
+}
+
+.col-xs-pull-4 {
+  right: 33.33333333333333%;
+}
+
+.col-xs-pull-3 {
+  right: 25%;
+}
+
+.col-xs-pull-2 {
+  right: 16.666666666666664%;
+}
+
+.col-xs-pull-1 {
+  right: 8.333333333333332%;
+}
+
+.col-xs-pull-0 {
+  right: 0;
+}
+
+.col-xs-push-12 {
+  left: 100%;
+}
+
+.col-xs-push-11 {
+  left: 91.66666666666666%;
+}
+
+.col-xs-push-10 {
+  left: 83.33333333333334%;
+}
+
+.col-xs-push-9 {
+  left: 75%;
+}
+
+.col-xs-push-8 {
+  left: 66.66666666666666%;
+}
+
+.col-xs-push-7 {
+  left: 58.333333333333336%;
+}
+
+.col-xs-push-6 {
+  left: 50%;
+}
+
+.col-xs-push-5 {
+  left: 41.66666666666667%;
+}
+
+.col-xs-push-4 {
+  left: 33.33333333333333%;
+}
+
+.col-xs-push-3 {
+  left: 25%;
+}
+
+.col-xs-push-2 {
+  left: 16.666666666666664%;
+}
+
+.col-xs-push-1 {
+  left: 8.333333333333332%;
+}
+
+.col-xs-push-0 {
+  left: 0;
+}
+
+.col-xs-offset-12 {
+  margin-left: 100%;
+}
+
+.col-xs-offset-11 {
+  margin-left: 91.66666666666666%;
+}
+
+.col-xs-offset-10 {
+  margin-left: 83.33333333333334%;
+}
+
+.col-xs-offset-9 {
+  margin-left: 75%;
+}
+
+.col-xs-offset-8 {
+  margin-left: 66.66666666666666%;
+}
+
+.col-xs-offset-7 {
+  margin-left: 58.333333333333336%;
+}
+
+.col-xs-offset-6 {
+  margin-left: 50%;
+}
+
+.col-xs-offset-5 {
+  margin-left: 41.66666666666667%;
+}
+
+.col-xs-offset-4 {
+  margin-left: 33.33333333333333%;
+}
+
+.col-xs-offset-3 {
+  margin-left: 25%;
+}
+
+.col-xs-offset-2 {
+  margin-left: 16.666666666666664%;
+}
+
+.col-xs-offset-1 {
+  margin-left: 8.333333333333332%;
+}
+
+.col-xs-offset-0 {
+  margin-left: 0;
+}
+
+@media (min-width: 768px) {
+  .col-sm-1,
+  .col-sm-2,
+  .col-sm-3,
+  .col-sm-4,
+  .col-sm-5,
+  .col-sm-6,
+  .col-sm-7,
+  .col-sm-8,
+  .col-sm-9,
+  .col-sm-10,
+  .col-sm-11,
+  .col-sm-12 {
+    float: left;
+  }
+  .col-sm-12 {
+    width: 100%;
+  }
+  .col-sm-11 {
+    width: 91.66666666666666%;
+  }
+  .col-sm-10 {
+    width: 83.33333333333334%;
+  }
+  .col-sm-9 {
+    width: 75%;
+  }
+  .col-sm-8 {
+    width: 66.66666666666666%;
+  }
+  .col-sm-7 {
+    width: 58.333333333333336%;
+  }
+  .col-sm-6 {
+    width: 50%;
+  }
+  .col-sm-5 {
+    width: 41.66666666666667%;
+  }
+  .col-sm-4 {
+    width: 33.33333333333333%;
+  }
+  .col-sm-3 {
+    width: 25%;
+  }
+  .col-sm-2 {
+    width: 16.666666666666664%;
+  }
+  .col-sm-1 {
+    width: 8.333333333333332%;
+  }
+  .col-sm-pull-12 {
+    right: 100%;
+  }
+  .col-sm-pull-11 {
+    right: 91.66666666666666%;
+  }
+  .col-sm-pull-10 {
+    right: 83.33333333333334%;
+  }
+  .col-sm-pull-9 {
+    right: 75%;
+  }
+  .col-sm-pull-8 {
+    right: 66.66666666666666%;
+  }
+  .col-sm-pull-7 {
+    right: 58.333333333333336%;
+  }
+  .col-sm-pull-6 {
+    right: 50%;
+  }
+  .col-sm-pull-5 {
+    right: 41.66666666666667%;
+  }
+  .col-sm-pull-4 {
+    right: 33.33333333333333%;
+  }
+  .col-sm-pull-3 {
+    right: 25%;
+  }
+  .col-sm-pull-2 {
+    right: 16.666666666666664%;
+  }
+  .col-sm-pull-1 {
+    right: 8.333333333333332%;
+  }
+  .col-sm-pull-0 {
+    right: 0;
+  }
+  .col-sm-push-12 {
+    left: 100%;
+  }
+  .col-sm-push-11 {
+    left: 91.66666666666666%;
+  }
+  .col-sm-push-10 {
+    left: 83.33333333333334%;
+  }
+  .col-sm-push-9 {
+    left: 75%;
+  }
+  .col-sm-push-8 {
+    left: 66.66666666666666%;
+  }
+  .col-sm-push-7 {
+    left: 58.333333333333336%;
+  }
+  .col-sm-push-6 {
+    left: 50%;
+  }
+  .col-sm-push-5 {
+    left: 41.66666666666667%;
+  }
+  .col-sm-push-4 {
+    left: 33.33333333333333%;
+  }
+  .col-sm-push-3 {
+    left: 25%;
+  }
+  .col-sm-push-2 {
+    left: 16.666666666666664%;
+  }
+  .col-sm-push-1 {
+    left: 8.333333333333332%;
+  }
+  .col-sm-push-0 {
+    left: 0;
+  }
+  .col-sm-offset-12 {
+    margin-left: 100%;
+  }
+  .col-sm-offset-11 {
+    margin-left: 91.66666666666666%;
+  }
+  .col-sm-offset-10 {
+    margin-left: 83.33333333333334%;
+  }
+  .col-sm-offset-9 {
+    margin-left: 75%;
+  }
+  .col-sm-offset-8 {
+    margin-left: 66.66666666666666%;
+  }
+  .col-sm-offset-7 {
+    margin-left: 58.333333333333336%;
+  }
+  .col-sm-offset-6 {
+    margin-left: 50%;
+  }
+  .col-sm-offset-5 {
+    margin-left: 41.66666666666667%;
+  }
+  .col-sm-offset-4 {
+    margin-left: 33.33333333333333%;
+  }
+  .col-sm-offset-3 {
+    margin-left: 25%;
+  }
+  .col-sm-offset-2 {
+    margin-left: 16.666666666666664%;
+  }
+  .col-sm-offset-1 {
+    margin-left: 8.333333333333332%;
+  }
+  .col-sm-offset-0 {
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-md-1,
+  .col-md-2,
+  .col-md-3,
+  .col-md-4,
+  .col-md-5,
+  .col-md-6,
+  .col-md-7,
+  .col-md-8,
+  .col-md-9,
+  .col-md-10,
+  .col-md-11,
+  .col-md-12 {
+    float: left;
+  }
+  .col-md-12 {
+    width: 100%;
+  }
+  .col-md-11 {
+    width: 91.66666666666666%;
+  }
+  .col-md-10 {
+    width: 83.33333333333334%;
+  }
+  .col-md-9 {
+    width: 75%;
+  }
+  .col-md-8 {
+    width: 66.66666666666666%;
+  }
+  .col-md-7 {
+    width: 58.333333333333336%;
+  }
+  .col-md-6 {
+    width: 50%;
+  }
+  .col-md-5 {
+    width: 41.66666666666667%;
+  }
+  .col-md-4 {
+    width: 33.33333333333333%;
+  }
+  .col-md-3 {
+    width: 25%;
+  }
+  .col-md-2 {
+    width: 16.666666666666664%;
+  }
+  .col-md-1 {
+    width: 8.333333333333332%;
+  }
+  .col-md-pull-12 {
+    right: 100%;
+  }
+  .col-md-pull-11 {
+    right: 91.66666666666666%;
+  }
+  .col-md-pull-10 {
+    right: 83.33333333333334%;
+  }
+  .col-md-pull-9 {
+    right: 75%;
+  }
+  .col-md-pull-8 {
+    right: 66.66666666666666%;
+  }
+  .col-md-pull-7 {
+    right: 58.333333333333336%;
+  }
+  .col-md-pull-6 {
+    right: 50%;
+  }
+  .col-md-pull-5 {
+    right: 41.66666666666667%;
+  }
+  .col-md-pull-4 {
+    right: 33.33333333333333%;
+  }
+  .col-md-pull-3 {
+    right: 25%;
+  }
+  .col-md-pull-2 {
+    right: 16.666666666666664%;
+  }
+  .col-md-pull-1 {
+    right: 8.333333333333332%;
+  }
+  .col-md-pull-0 {
+    right: 0;
+  }
+  .col-md-push-12 {
+    left: 100%;
+  }
+  .col-md-push-11 {
+    left: 91.66666666666666%;
+  }
+  .col-md-push-10 {
+    left: 83.33333333333334%;
+  }
+  .col-md-push-9 {
+    left: 75%;
+  }
+  .col-md-push-8 {
+    left: 66.66666666666666%;
+  }
+  .col-md-push-7 {
+    left: 58.333333333333336%;
+  }
+  .col-md-push-6 {
+    left: 50%;
+  }
+  .col-md-push-5 {
+    left: 41.66666666666667%;
+  }
+  .col-md-push-4 {
+    left: 33.33333333333333%;
+  }
+  .col-md-push-3 {
+    left: 25%;
+  }
+  .col-md-push-2 {
+    left: 16.666666666666664%;
+  }
+  .col-md-push-1 {
+    left: 8.333333333333332%;
+  }
+  .col-md-push-0 {
+    left: 0;
+  }
+  .col-md-offset-12 {
+    margin-left: 100%;
+  }
+  .col-md-offset-11 {
+    margin-left: 91.66666666666666%;
+  }
+  .col-md-offset-10 {
+    margin-left: 83.33333333333334%;
+  }
+  .col-md-offset-9 {
+    margin-left: 75%;
+  }
+  .col-md-offset-8 {
+    margin-left: 66.66666666666666%;
+  }
+  .col-md-offset-7 {
+    margin-left: 58.333333333333336%;
+  }
+  .col-md-offset-6 {
+    margin-left: 50%;
+  }
+  .col-md-offset-5 {
+    margin-left: 41.66666666666667%;
+  }
+  .col-md-offset-4 {
+    margin-left: 33.33333333333333%;
+  }
+  .col-md-offset-3 {
+    margin-left: 25%;
+  }
+  .col-md-offset-2 {
+    margin-left: 16.666666666666664%;
+  }
+  .col-md-offset-1 {
+    margin-left: 8.333333333333332%;
+  }
+  .col-md-offset-0 {
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-lg-1,
+  .col-lg-2,
+  .col-lg-3,
+  .col-lg-4,
+  .col-lg-5,
+  .col-lg-6,
+  .col-lg-7,
+  .col-lg-8,
+  .col-lg-9,
+  .col-lg-10,
+  .col-lg-11,
+  .col-lg-12 {
+    float: left;
+  }
+  .col-lg-12 {
+    width: 100%;
+  }
+  .col-lg-11 {
+    width: 91.66666666666666%;
+  }
+  .col-lg-10 {
+    width: 83.33333333333334%;
+  }
+  .col-lg-9 {
+    width: 75%;
+  }
+  .col-lg-8 {
+    width: 66.66666666666666%;
+  }
+  .col-lg-7 {
+    width: 58.333333333333336%;
+  }
+  .col-lg-6 {
+    width: 50%;
+  }
+  .col-lg-5 {
+    width: 41.66666666666667%;
+  }
+  .col-lg-4 {
+    width: 33.33333333333333%;
+  }
+  .col-lg-3 {
+    width: 25%;
+  }
+  .col-lg-2 {
+    width: 16.666666666666664%;
+  }
+  .col-lg-1 {
+    width: 8.333333333333332%;
+  }
+  .col-lg-pull-12 {
+    right: 100%;
+  }
+  .col-lg-pull-11 {
+    right: 91.66666666666666%;
+  }
+  .col-lg-pull-10 {
+    right: 83.33333333333334%;
+  }
+  .col-lg-pull-9 {
+    right: 75%;
+  }
+  .col-lg-pull-8 {
+    right: 66.66666666666666%;
+  }
+  .col-lg-pull-7 {
+    right: 58.333333333333336%;
+  }
+  .col-lg-pull-6 {
+    right: 50%;
+  }
+  .col-lg-pull-5 {
+    right: 41.66666666666667%;
+  }
+  .col-lg-pull-4 {
+    right: 33.33333333333333%;
+  }
+  .col-lg-pull-3 {
+    right: 25%;
+  }
+  .col-lg-pull-2 {
+    right: 16.666666666666664%;
+  }
+  .col-lg-pull-1 {
+    right: 8.333333333333332%;
+  }
+  .col-lg-pull-0 {
+    right: 0;
+  }
+  .col-lg-push-12 {
+    left: 100%;
+  }
+  .col-lg-push-11 {
+    left: 91.66666666666666%;
+  }
+  .col-lg-push-10 {
+    left: 83.33333333333334%;
+  }
+  .col-lg-push-9 {
+    left: 75%;
+  }
+  .col-lg-push-8 {
+    left: 66.66666666666666%;
+  }
+  .col-lg-push-7 {
+    left: 58.333333333333336%;
+  }
+  .col-lg-push-6 {
+    left: 50%;
+  }
+  .col-lg-push-5 {
+    left: 41.66666666666667%;
+  }
+  .col-lg-push-4 {
+    left: 33.33333333333333%;
+  }
+  .col-lg-push-3 {
+    left: 25%;
+  }
+  .col-lg-push-2 {
+    left: 16.666666666666664%;
+  }
+  .col-lg-push-1 {
+    left: 8.333333333333332%;
+  }
+  .col-lg-push-0 {
+    left: 0;
+  }
+  .col-lg-offset-12 {
+    margin-left: 100%;
+  }
+  .col-lg-offset-11 {
+    margin-left: 91.66666666666666%;
+  }
+  .col-lg-offset-10 {
+    margin-left: 83.33333333333334%;
+  }
+  .col-lg-offset-9 {
+    margin-left: 75%;
+  }
+  .col-lg-offset-8 {
+    margin-left: 66.66666666666666%;
+  }
+  .col-lg-offset-7 {
+    margin-left: 58.333333333333336%;
+  }
+  .col-lg-offset-6 {
+    margin-left: 50%;
+  }
+  .col-lg-offset-5 {
+    margin-left: 41.66666666666667%;
+  }
+  .col-lg-offset-4 {
+    margin-left: 33.33333333333333%;
+  }
+  .col-lg-offset-3 {
+    margin-left: 25%;
+  }
+  .col-lg-offset-2 {
+    margin-left: 16.666666666666664%;
+  }
+  .col-lg-offset-1 {
+    margin-left: 8.333333333333332%;
+  }
+  .col-lg-offset-0 {
+    margin-left: 0;
+  }
+}
+
+table {
+  max-width: 100%;
+  background-color: transparent;
+}
+
+th {
+  text-align: left;
+}
+
+.table {
+  width: 100%;
+  margin-bottom: 20px;
+}
+
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+  padding: 8px;
+  line-height: 1.428571429;
+  vertical-align: top;
+  border-top: 1px solid #dddddd;
+}
+
+.table > thead > tr > th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #dddddd;
+}
+
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.table > thead:first-child > tr:first-child > td {
+  border-top: 0;
+}
+
+.table > tbody + tbody {
+  border-top: 2px solid #dddddd;
+}
+
+.table .table {
+  background-color: #ffffff;
+}
+
+.table-condensed > thead > tr > th,
+.table-condensed > tbody > tr > th,
+.table-condensed > tfoot > tr > th,
+.table-condensed > thead > tr > td,
+.table-condensed > tbody > tr > td,
+.table-condensed > tfoot > tr > td {
+  padding: 5px;
+}
+
+.table-bordered {
+  border: 1px solid #dddddd;
+}
+
+.table-bordered > thead > tr > th,
+.table-bordered > tbody > tr > th,
+.table-bordered > tfoot > tr > th,
+.table-bordered > thead > tr > td,
+.table-bordered > tbody > tr > td,
+.table-bordered > tfoot > tr > td {
+  border: 1px solid #dddddd;
+}
+
+.table-bordered > thead > tr > th,
+.table-bordered > thead > tr > td {
+  border-bottom-width: 2px;
+}
+
+.table-striped > tbody > tr:nth-child(odd) > td,
+.table-striped > tbody > tr:nth-child(odd) > th {
+  background-color: #f9f9f9;
+}
+
+.table-hover > tbody > tr:hover > td,
+.table-hover > tbody > tr:hover > th {
+  background-color: #f5f5f5;
+}
+
+table col[class*="col-"] {
+  position: static;
+  display: table-column;
+  float: none;
+}
+
+table td[class*="col-"],
+table th[class*="col-"] {
+  display: table-cell;
+  float: none;
+}
+
+.table > thead > tr > .active,
+.table > tbody > tr > .active,
+.table > tfoot > tr > .active,
+.table > thead > .active > td,
+.table > tbody > .active > td,
+.table > tfoot > .active > td,
+.table > thead > .active > th,
+.table > tbody > .active > th,
+.table > tfoot > .active > th {
+  background-color: #f5f5f5;
+}
+
+.table-hover > tbody > tr > .active:hover,
+.table-hover > tbody > .active:hover > td,
+.table-hover > tbody > .active:hover > th {
+  background-color: #e8e8e8;
+}
+
+.table > thead > tr > .success,
+.table > tbody > tr > .success,
+.table > tfoot > tr > .success,
+.table > thead > .success > td,
+.table > tbody > .success > td,
+.table > tfoot > .success > td,
+.table > thead > .success > th,
+.table > tbody > .success > th,
+.table > tfoot > .success > th {
+  background-color: #dff0d8;
+}
+
+.table-hover > tbody > tr > .success:hover,
+.table-hover > tbody > .success:hover > td,
+.table-hover > tbody > .success:hover > th {
+  background-color: #d0e9c6;
+}
+
+.table > thead > tr > .danger,
+.table > tbody > tr > .danger,
+.table > tfoot > tr > .danger,
+.table > thead > .danger > td,
+.table > tbody > .danger > td,
+.table > tfoot > .danger > td,
+.table > thead > .danger > th,
+.table > tbody > .danger > th,
+.table > tfoot > .danger > th {
+  background-color: #f2dede;
+}
+
+.table-hover > tbody > tr > .danger:hover,
+.table-hover > tbody > .danger:hover > td,
+.table-hover > tbody > .danger:hover > th {
+  background-color: #ebcccc;
+}
+
+.table > thead > tr > .warning,
+.table > tbody > tr > .warning,
+.table > tfoot > tr > .warning,
+.table > thead > .warning > td,
+.table > tbody > .warning > td,
+.table > tfoot > .warning > td,
+.table > thead > .warning > th,
+.table > tbody > .warning > th,
+.table > tfoot > .warning > th {
+  background-color: #fcf8e3;
+}
+
+.table-hover > tbody > tr > .warning:hover,
+.table-hover > tbody > .warning:hover > td,
+.table-hover > tbody > .warning:hover > th {
+  background-color: #faf2cc;
+}
+
+@media (max-width: 767px) {
+  .table-responsive {
+    width: 100%;
+    margin-bottom: 15px;
+    overflow-x: scroll;
+    overflow-y: hidden;
+    border: 1px solid #dddddd;
+    -ms-overflow-style: -ms-autohiding-scrollbar;
+    -webkit-overflow-scrolling: touch;
+  }
+  .table-responsive > .table {
+    margin-bottom: 0;
+  }
+  .table-responsive > .table > thead > tr > th,
+  .table-responsive > .table > tbody > tr > th,
+  .table-responsive > .table > tfoot > tr > th,
+  .table-responsive > .table > thead > tr > td,
+  .table-responsive > .table > tbody > tr > td,
+  .table-responsive > .table > tfoot > tr > td {
+    white-space: nowrap;
+  }
+  .table-responsive > .table-bordered {
+    border: 0;
+  }
+  .table-responsive > .table-bordered > thead > tr > th:first-child,
+  .table-responsive > .table-bordered > tbody > tr > th:first-child,
+  .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+  .table-responsive > .table-bordered > thead > tr > td:first-child,
+  .table-responsive > .table-bordered > tbody > tr > td:first-child,
+  .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+    border-left: 0;
+  }
+  .table-responsive > .table-bordered > thead > tr > th:last-child,
+  .table-responsive > .table-bordered > tbody > tr > th:last-child,
+  .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+  .table-responsive > .table-bordered > thead > tr > td:last-child,
+  .table-responsive > .table-bordered > tbody > tr > td:last-child,
+  .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+    border-right: 0;
+  }
+  .table-responsive > .table-bordered > tbody > tr:last-child > th,
+  .table-responsive > .table-bordered > tfoot > tr:last-child > th,
+  .table-responsive > .table-bordered > tbody > tr:last-child > td,
+  .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+    border-bottom: 0;
+  }
+}
+
+fieldset {
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: 20px;
+  font-size: 21px;
+  line-height: inherit;
+  color: #333333;
+  border: 0;
+  border-bottom: 1px solid #e5e5e5;
+}
+
+label {
+  display: inline-block;
+  margin-bottom: 5px;
+  font-weight: bold;
+}
+
+input[type="search"] {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+input[type="radio"],
+input[type="checkbox"] {
+  margin: 4px 0 0;
+  margin-top: 1px \9;
+  /* IE8-9 */
+
+  line-height: normal;
+}
+
+input[type="file"] {
+  display: block;
+}
+
+select[multiple],
+select[size] {
+  height: auto;
+}
+
+select optgroup {
+  font-family: inherit;
+  font-size: inherit;
+  font-style: inherit;
+}
+
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+input[type="number"]::-webkit-outer-spin-button,
+input[type="number"]::-webkit-inner-spin-button {
+  height: auto;
+}
+
+output {
+  display: block;
+  padding-top: 7px;
+  font-size: 14px;
+  line-height: 1.428571429;
+  color: #555555;
+  vertical-align: middle;
+}
+
+.form-control {
+  display: block;
+  width: 100%;
+  height: 34px;
+  padding: 6px 12px;
+  font-size: 14px;
+  line-height: 1.428571429;
+  color: #555555;
+  vertical-align: middle;
+  background-color: #ffffff;
+  background-image: none;
+  border: 1px solid #cccccc;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+          transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+}
+
+.form-control:focus {
+  border-color: #66afe9;
+  outline: 0;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+
+.form-control:-moz-placeholder {
+  color: #999999;
+}
+
+.form-control::-moz-placeholder {
+  color: #999999;
+  opacity: 1;
+}
+
+.form-control:-ms-input-placeholder {
+  color: #999999;
+}
+
+.form-control::-webkit-input-placeholder {
+  color: #999999;
+}
+
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+  cursor: not-allowed;
+  background-color: #eeeeee;
+}
+
+textarea.form-control {
+  height: auto;
+}
+
+.form-group {
+  margin-bottom: 15px;
+}
+
+.radio,
+.checkbox {
+  display: block;
+  min-height: 20px;
+  padding-left: 20px;
+  margin-top: 10px;
+  margin-bottom: 10px;
+  vertical-align: middle;
+}
+
+.radio label,
+.checkbox label {
+  display: inline;
+  margin-bottom: 0;
+  font-weight: normal;
+  cursor: pointer;
+}
+
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+  float: left;
+  margin-left: -20px;
+}
+
+.radio + .radio,
+.checkbox + .checkbox {
+  margin-top: -5px;
+}
+
+.radio-inline,
+.checkbox-inline {
+  display: inline-block;
+  padding-left: 20px;
+  margin-bottom: 0;
+  font-weight: normal;
+  vertical-align: middle;
+  cursor: pointer;
+}
+
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+  margin-top: 0;
+  margin-left: 10px;
+}
+
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+.radio[disabled],
+.radio-inline[disabled],
+.checkbox[disabled],
+.checkbox-inline[disabled],
+fieldset[disabled] input[type="radio"],
+fieldset[disabled] input[type="checkbox"],
+fieldset[disabled] .radio,
+fieldset[disabled] .radio-inline,
+fieldset[disabled] .checkbox,
+fieldset[disabled] .checkbox-inline {
+  cursor: not-allowed;
+}
+
+.input-sm {
+  height: 30px;
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+
+select.input-sm {
+  height: 30px;
+  line-height: 30px;
+}
+
+textarea.input-sm {
+  height: auto;
+}
+
+.input-lg {
+  height: 46px;
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.33;
+  border-radius: 6px;
+}
+
+select.input-lg {
+  height: 46px;
+  line-height: 46px;
+}
+
+textarea.input-lg {
+  height: auto;
+}
+
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline {
+  color: #8a6d3b;
+}
+
+.has-warning .form-control {
+  border-color: #8a6d3b;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.has-warning .form-control:focus {
+  border-color: #66512c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;
+}
+
+.has-warning .input-group-addon {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+  border-color: #8a6d3b;
+}
+
+.has-error .help-block,
+.has-error .control-label,
+.has-error .radio,
+.has-error .checkbox,
+.has-error .radio-inline,
+.has-error .checkbox-inline {
+  color: #a94442;
+}
+
+.has-error .form-control {
+  border-color: #a94442;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.has-error .form-control:focus {
+  border-color: #843534;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
+}
+
+.has-error .input-group-addon {
+  color: #a94442;
+  background-color: #f2dede;
+  border-color: #a94442;
+}
+
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline {
+  color: #3c763d;
+}
+
+.has-success .form-control {
+  border-color: #3c763d;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.has-success .form-control:focus {
+  border-color: #2b542c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
+}
+
+.has-success .input-group-addon {
+  color: #3c763d;
+  background-color: #dff0d8;
+  border-color: #3c763d;
+}
+
+.form-control-static {
+  margin-bottom: 0;
+}
+
+.help-block {
+  display: block;
+  margin-top: 5px;
+  margin-bottom: 10px;
+  color: #737373;
+}
+
+@media (min-width: 768px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+  }
+  .form-inline select.form-control {
+    width: auto;
+  }
+  .form-inline .radio,
+  .form-inline .checkbox {
+    display: inline-block;
+    padding-left: 0;
+    margin-top: 0;
+    margin-bottom: 0;
+  }
+  .form-inline .radio input[type="radio"],
+  .form-inline .checkbox input[type="checkbox"] {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+.form-horizontal .control-label,
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+  padding-top: 7px;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+  min-height: 27px;
+}
+
+.form-horizontal .form-group {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after {
+  display: table;
+  content: " ";
+}
+
+.form-horizontal .form-group:after {
+  clear: both;
+}
+
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after {
+  display: table;
+  content: " ";
+}
+
+.form-horizontal .form-group:after {
+  clear: both;
+}
+
+.form-horizontal .form-control-static {
+  padding-top: 7px;
+}
+
+@media (min-width: 768px) {
+  .form-horizontal .control-label {
+    text-align: right;
+  }
+}
+
+.btn {
+  display: inline-block;
+  padding: 6px 12px;
+  margin-bottom: 0;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 1.428571429;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  cursor: pointer;
+  background-image: none;
+  border: 1px solid transparent;
+  border-radius: 4px;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+       -o-user-select: none;
+          user-select: none;
+}
+
+.btn:focus {
+  outline: thin dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.btn:hover,
+.btn:focus {
+  color: #333333;
+  text-decoration: none;
+}
+
+.btn:active,
+.btn.active {
+  background-image: none;
+  outline: 0;
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+  pointer-events: none;
+  cursor: not-allowed;
+  opacity: 0.65;
+  filter: alpha(opacity=65);
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+
+.btn-default {
+  color: #333333;
+  background-color: #ffffff;
+  border-color: #cccccc;
+}
+
+.btn-default:hover,
+.btn-default:focus,
+.btn-default:active,
+.btn-default.active,
+.open .dropdown-toggle.btn-default {
+  color: #333333;
+  background-color: #ebebeb;
+  border-color: #adadad;
+}
+
+.btn-default:active,
+.btn-default.active,
+.open .dropdown-toggle.btn-default {
+  background-image: none;
+}
+
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+  background-color: #ffffff;
+  border-color: #cccccc;
+}
+
+.btn-default .badge {
+  color: #ffffff;
+  background-color: #fff;
+}
+
+.btn-primary {
+  color: #ffffff;
+  background-color: #428bca;
+  border-color: #357ebd;
+}
+
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary:active,
+.btn-primary.active,
+.open .dropdown-toggle.btn-primary {
+  color: #ffffff;
+  background-color: #3276b1;
+  border-color: #285e8e;
+}
+
+.btn-primary:active,
+.btn-primary.active,
+.open .dropdown-toggle.btn-primary {
+  background-image: none;
+}
+
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+  background-color: #428bca;
+  border-color: #357ebd;
+}
+
+.btn-primary .badge {
+  color: #428bca;
+  background-color: #fff;
+}
+
+.btn-warning {
+  color: #ffffff;
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning:active,
+.btn-warning.active,
+.open .dropdown-toggle.btn-warning {
+  color: #ffffff;
+  background-color: #ed9c28;
+  border-color: #d58512;
+}
+
+.btn-warning:active,
+.btn-warning.active,
+.open .dropdown-toggle.btn-warning {
+  background-image: none;
+}
+
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+  background-color: #f0ad4e;
+  border-color: #eea236;
+}
+
+.btn-warning .badge {
+  color: #f0ad4e;
+  background-color: #fff;
+}
+
+.btn-danger {
+  color: #ffffff;
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger:active,
+.btn-danger.active,
+.open .dropdown-toggle.btn-danger {
+  color: #ffffff;
+  background-color: #d2322d;
+  border-color: #ac2925;
+}
+
+.btn-danger:active,
+.btn-danger.active,
+.open .dropdown-toggle.btn-danger {
+  background-image: none;
+}
+
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+  background-color: #d9534f;
+  border-color: #d43f3a;
+}
+
+.btn-danger .badge {
+  color: #d9534f;
+  background-color: #fff;
+}
+
+.btn-success {
+  color: #ffffff;
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+
+.btn-success:hover,
+.btn-success:focus,
+.btn-success:active,
+.btn-success.active,
+.open .dropdown-toggle.btn-success {
+  color: #ffffff;
+  background-color: #47a447;
+  border-color: #398439;
+}
+
+.btn-success:active,
+.btn-success.active,
+.open .dropdown-toggle.btn-success {
+  background-image: none;
+}
+
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+  background-color: #5cb85c;
+  border-color: #4cae4c;
+}
+
+.btn-success .badge {
+  color: #5cb85c;
+  background-color: #fff;
+}
+
+.btn-info {
+  color: #ffffff;
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+
+.btn-info:hover,
+.btn-info:focus,
+.btn-info:active,
+.btn-info.active,
+.open .dropdown-toggle.btn-info {
+  color: #ffffff;
+  background-color: #39b3d7;
+  border-color: #269abc;
+}
+
+.btn-info:active,
+.btn-info.active,
+.open .dropdown-toggle.btn-info {
+  background-image: none;
+}
+
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+  background-color: #5bc0de;
+  border-color: #46b8da;
+}
+
+.btn-info .badge {
+  color: #5bc0de;
+  background-color: #fff;
+}
+
+.btn-link {
+  font-weight: normal;
+  color: #428bca;
+  cursor: pointer;
+  border-radius: 0;
+}
+
+.btn-link,
+.btn-link:active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+  background-color: transparent;
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+  border-color: transparent;
+}
+
+.btn-link:hover,
+.btn-link:focus {
+  color: #2a6496;
+  text-decoration: underline;
+  background-color: transparent;
+}
+
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+  color: #999999;
+  text-decoration: none;
+}
+
+.btn-lg {
+  padding: 10px 16px;
+  font-size: 18px;
+  line-height: 1.33;
+  border-radius: 6px;
+}
+
+.btn-sm {
+  padding: 5px 10px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+
+.btn-xs {
+  padding: 1px 5px;
+  font-size: 12px;
+  line-height: 1.5;
+  border-radius: 3px;
+}
+
+.btn-block {
+  display: block;
+  width: 100%;
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.btn-block + .btn-block {
+  margin-top: 5px;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity 0.15s linear;
+          transition: opacity 0.15s linear;
+}
+
+.fade.in {
+  opacity: 1;
+}
+
+.collapse {
+  display: none;
+}
+
+.collapse.in {
+  display: block;
+}
+
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition: height 0.35s ease;
+          transition: height 0.35s ease;
+}
+
+@font-face {
+  font-family: 'Glyphicons Halflings';
+  src: url('../fonts/glyphicons-halflings-regular.eot');
+  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
+}
+
+.glyphicon {
+  position: relative;
+  top: 1px;
+  display: inline-block;
+  font-family: 'Glyphicons Halflings';
+  -webkit-font-smoothing: antialiased;
+  font-style: normal;
+  font-weight: normal;
+  line-height: 1;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.glyphicon:empty {
+  width: 1em;
+}
+
+.glyphicon-asterisk:before {
+  content: "\2a";
+}
+
+.glyphicon-plus:before {
+  content: "\2b";
+}
+
+.glyphicon-euro:before {
+  content: "\20ac";
+}
+
+.glyphicon-minus:before {
+  content: "\2212";
+}
+
+.glyphicon-cloud:before {
+  content: "\2601";
+}
+
+.glyphicon-envelope:before {
+  content: "\2709";
+}
+
+.glyphicon-pencil:before {
+  content: "\270f";
+}
+
+.glyphicon-glass:before {
+  content: "\e001";
+}
+
+.glyphicon-music:before {
+  content: "\e002";
+}
+
+.glyphicon-search:before {
+  content: "\e003";
+}
+
+.glyphicon-heart:before {
+  content: "\e005";
+}
+
+.glyphicon-star:before {
+  content: "\e006";
+}
+
+.glyphicon-star-empty:before {
+  content: "\e007";
+}
+
+.glyphicon-user:before {
+  content: "\e008";
+}
+
+.glyphicon-film:before {
+  content: "\e009";
+}
+
+.glyphicon-th-large:before {
+  content: "\e010";
+}
+
+.glyphicon-th:before {
+  content: "\e011";
+}
+
+.glyphicon-th-list:before {
+  content: "\e012";
+}
+
+.glyphicon-ok:before {
+  content: "\e013";
+}
+
+.glyphicon-remove:before {
+  content: "\e014";
+}
+
+.glyphicon-zoom-in:before {
+  content: "\e015";
+}
+
+.glyphicon-zoom-out:before {
+  content: "\e016";
+}
+
+.glyphicon-off:before {
+  content: "\e017";
+}
+
+.glyphicon-signal:before {
+  content: "\e018";
+}
+
+.glyphicon-cog:before {
+  content: "\e019";
+}
+
+.glyphicon-trash:before {
+  content: "\e020";
+}
+
+.glyphicon-home:before {
+  content: "\e021";
+}
+
+.glyphicon-file:before {
+  content: "\e022";
+}
+
+.glyphicon-time:before {
+  content: "\e023";
+}
+
+.glyphicon-road:before {
+  content: "\e024";
+}
+
+.glyphicon-download-alt:before {
+  content: "\e025";
+}
+
+.glyphicon-download:before {
+  content: "\e026";
+}
+
+.glyphicon-upload:before {
+  content: "\e027";
+}
+
+.glyphicon-inbox:before {
+  content: "\e028";
+}
+
+.glyphicon-play-circle:before {
+  content: "\e029";
+}
+
+.glyphicon-repeat:before {
+  content: "\e030";
+}
+
+.glyphicon-refresh:before {
+  content: "\e031";
+}
+
+.glyphicon-list-alt:before {
+  content: "\e032";
+}
+
+.glyphicon-lock:before {
+  content: "\e033";
+}
+
+.glyphicon-flag:before {
+  content: "\e034";
+}
+
+.glyphicon-headphones:before {
+  content: "\e035";
+}
+
+.glyphicon-volume-off:before {
+  content: "\e036";
+}
+
+.glyphicon-volume-down:before {
+  content: "\e037";
+}
+
+.glyphicon-volume-up:before {
+  content: "\e038";
+}
+
+.glyphicon-qrcode:before {
+  content: "\e039";
+}
+
+.glyphicon-barcode:before {
+  content: "\e040";
+}
+
+.glyphicon-tag:before {
+  content: "\e041";
+}
+
+.glyphicon-tags:before {
+  content: "\e042";
+}
+
+.glyphicon-book:before {
+  content: "\e043";
+}
+
+.glyphicon-bookmark:before {
+  content: "\e044";
+}
+
+.glyphicon-print:before {
+  content: "\e045";
+}
+
+.glyphicon-camera:before {
+  content: "\e046";
+}
+
+.glyphicon-font:before {
+  content: "\e047";
+}
+
+.glyphicon-bold:before {
+  content: "\e048";
+}
+
+.glyphicon-italic:before {
+  content: "\e049";
+}
+
+.glyphicon-text-height:before {
+  content: "\e050";
+}
+
+.glyphicon-text-width:before {
+  content: "\e051";
+}
+
+.glyphicon-align-left:before {
+  content: "\e052";
+}
+
+.glyphicon-align-center:before {
+  content: "\e053";
+}
+
+.glyphicon-align-right:before {
+  content: "\e054";
+}
+
+.glyphicon-align-justify:before {
+  content: "\e055";
+}
+
+.glyphicon-list:before {
+  content: "\e056";
+}
+
+.glyphicon-indent-left:before {
+  content: "\e057";
+}
+
+.glyphicon-indent-right:before {
+  content: "\e058";
+}
+
+.glyphicon-facetime-video:before {
+  content: "\e059";
+}
+
+.glyphicon-picture:before {
+  content: "\e060";
+}
+
+.glyphicon-map-marker:before {
+  content: "\e062";
+}
+
+.glyphicon-adjust:before {
+  content: "\e063";
+}
+
+.glyphicon-tint:before {
+  content: "\e064";
+}
+
+.glyphicon-edit:before {
+  content: "\e065";
+}
+
+.glyphicon-share:before {
+  content: "\e066";
+}
+
... 29625 lines suppressed ...


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists