diff --git a/classes/MarketPlugin.class.php b/classes/MarketPlugin.class.php
index 1f40f62582f0e1bd9d0ead099565bd7f2962caaa..9cc8245582455c73beaa340cc534c89b09ece19e 100755
--- a/classes/MarketPlugin.class.php
+++ b/classes/MarketPlugin.class.php
@@ -170,4 +170,5 @@ class MarketPlugin extends SimpleORMap {
 
         return $rating;
     }
+
 }
\ No newline at end of file
diff --git a/classes/MarketRelease.class.php b/classes/MarketRelease.class.php
index c3ee241df2795b6f577e6d154703eedf49a31093..6286acc7ea189966ca905c5037fc366b408179e5 100755
--- a/classes/MarketRelease.class.php
+++ b/classes/MarketRelease.class.php
@@ -30,7 +30,7 @@ class MarketRelease extends SimpleORMap {
 
     public function delete() {
         parent::delete();
-        unlink($this->getFilePath());
+        @unlink($this->getFilePath());
     }
 
     public function installFile() {
@@ -56,7 +56,13 @@ class MarketRelease extends SimpleORMap {
         } else {
             $plugin_dir = $tmp_folder;
         }
-        $this->installFromDirectory($plugin_dir, $file);
+        try {
+            $this->installFromDirectory($plugin_dir, $file);
+        } catch (PluginInstallationException $e) {
+            rmdirr($tmp_folder);
+            unlink($file);
+            throw $e;
+        }
 
         rmdirr($tmp_folder);
         unlink($file);
@@ -80,7 +86,7 @@ class MarketRelease extends SimpleORMap {
         header('Content-Type: ' . $this->getMimeType());
         header('Content-Disposition: attachment; filename="' . $this->getFilename() . '"');
 
-        readfile($this->getFilePath());
+        @readfile($this->getFilePath());
     }
 
     public function getMimeType()
@@ -90,7 +96,7 @@ class MarketRelease extends SimpleORMap {
 
     public function getFilename()
     {
-        return $this->plugin['name'] . '.zip';
+        return $this->plugin['pluginname'] . '.zip';
     }
 
     public function getContentLength()
@@ -113,9 +119,26 @@ class MarketRelease extends SimpleORMap {
 
     protected function installFromDirectory($dir, $originalfile = null) {
         $manifest = PluginManager::getInstance()->getPluginManifest($dir);
-        if ($manifest['pluginclassname']) {
-            $this->plugin['pluginclassname'] = $manifest['pluginclassname'];
-            $this->plugin->store();
+        if ($manifest['pluginname']) {
+            if ($this->plugin->isNew()) {
+                $this->plugin['pluginname'] = $manifest['pluginname'];
+                $this->plugin['name'] = @$manifest['displayname'] ?: $manifest['pluginname'];
+                $this->plugin['short_description'] = @$manifest['description'] ?: '';
+                $this->plugin['description'] = @$manifest['descriptionlong'] ?: '';
+                if (!$this->plugin['description']) {
+                    $this['repository_overwrites_descriptionfrom'] = 1;
+                }
+                if (MarketPlugin::findOneByPluginname($this->plugin->pluginname)) {
+                    throw new PluginInstallationException(_("Ein Plugin mit diesem Namen ist schon im Marktplatz vorhanden!"));
+                }
+                $this->plugin->store();
+            } else {
+                if ($this->plugin['pluginname'] != $manifest['pluginname']) {
+                    throw new PluginInstallationException(sprintf(_("Release hat falschen Pluginnamen, erwartet:%s gefunden:%s"), $this->plugin['pluginname'], $manifest['pluginname']));
+                }
+            }
+        } else {
+            throw new PluginInstallationException(_("Im Manifest fehlt der Pluginname"));
         }
         $this['studip_min_version'] = $manifest['studipMinVersion'];
         $this['studip_max_version'] = $manifest['studipMaxVersion'];
@@ -198,4 +221,18 @@ class MarketRelease extends SimpleORMap {
         return implode("\n", $arr);
     }
 
+    public function getPluginName()
+    {
+        $zip = new ZipArchive();
+        if ($zip->open($this->getFilePath())) {
+            $manifest = $zip->getFromIndex($zip->locateName('plugin.manifest', ZipArchive::FL_NOCASE|ZipArchive::FL_NODIR));
+            foreach (array_map('trim',explode("\n", $manifest)) as $line) {
+                list($key, $value) = explode('=', $line);
+                if ($key === 'pluginname') {
+                    return trim($value);
+                }
+            }
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/controllers/extern.php b/controllers/extern.php
index b5e1bce2bde82220c3c70537930b5c974d7fdba1..9f89019554479195c500df6ccf68d68a8f292776 100755
--- a/controllers/extern.php
+++ b/controllers/extern.php
@@ -20,7 +20,8 @@ class ExternController extends MarketController
         $plugins = MarketPlugin::findBySQL("publiclyvisible = 1 AND approved = 1 ORDER BY name ASC");
         foreach ($plugins as $plugin) {
             $xml_plugin = $xml_plugins->appendChild($this->create_xml_element($doc, 'plugin', null, array(
-                'name'              => $plugin->name,
+                'displayname'       => $plugin->name,
+                'name'              => $plugin->pluginname,
                 'homepage'          => $plugin->url,
                 'short_description' => $plugin->short_description,
                 'description'       => $plugin->description,
diff --git a/controllers/myplugins.php b/controllers/myplugins.php
index ca345e1bee93d412c7ea74f564270ef2a4656a36..7896930c87a754369f2c092c62d4e3d4c3ecb50f 100755
--- a/controllers/myplugins.php
+++ b/controllers/myplugins.php
@@ -16,11 +16,28 @@ class MypluginsController extends MarketController
         $this->plugins = MarketPlugin::findBySQL("user_id = ? ORDER BY mkdate DESC", array($GLOBALS['user']->id));
     }
 
+    public function addfromzip_action()
+    {
+        CSRFProtection::verifyUnsafeRequest();
+        if (isset($_FILES['release_file']['tmp_name'])) {
+            $plugin = new MarketPlugin();
+            $plugin->setId($plugin->getNewId());
+            $plugin->user_id = $GLOBALS['user']->id;
+            $release = new MarketRelease();
+            $release->plugin = $plugin;
+            $release['user_id'] = $GLOBALS['user']->id;
+            //throws Exception on error
+            $release->installFile();
+            $this->redirect($this->url_for('/overview', ['edit_plugin_id' => $plugin->id]));
+        }
+    }
+
     public function add_action() {
         $this->marketplugin = new MarketPlugin();
         if (Request::isXhr()) {
             $this->set_layout(null);
         }
+
         $this->render_action("edit");
     }
 
@@ -80,6 +97,10 @@ class MypluginsController extends MarketController
                 $data['donationsaccepted'] = 0;
             }
             $this->marketplugin->setData($data);
+            if ($this->marketplugin->isNew() && (MarketPlugin::findOneByPluginname($this->marketplugin->pluginname) || !strlen(trim($this->marketplugin->pluginname)))) {
+                PageLayout::postError(_("Ein Plugin mit diesem Namen ist schon im Marktplatz vorhanden!"));
+                return $this->redirect($this->url_for('/overview'));
+            }
             if ($this->marketplugin->isNew()) {
                 $this->marketplugin['user_id'] = $GLOBALS['user']->id;
             }
@@ -129,9 +150,15 @@ class MypluginsController extends MarketController
                 $release->setData($release_data);
                 $release['plugin_id'] = $this->marketplugin->getId();
                 $release['user_id'] = $GLOBALS['user']->id;
-                $release->installFile();
-                $release->store();
+                try {
+                    $release->installFile();
+                } catch (PluginInstallationException $e) {
+                    PageLayout::postError($e->getMessage());
+
+                    return $this->redirect($this->url_for('/overview'));
+                }
             }
+
         }
         PageLayout::postMessage(MessageBox::success(_("Plugin wurde gespeichert.")));
         $this->redirect('presenting/details/' . $this->marketplugin->getId());
diff --git a/controllers/presenting.php b/controllers/presenting.php
index fe7335409a41d87ced51873323966febf135e94f..93ce2949d680bf579a7277bbbf6c0bff7666e2e0 100755
--- a/controllers/presenting.php
+++ b/controllers/presenting.php
@@ -115,6 +115,7 @@ class PresentingController extends MarketController
             $this->plugins = MarketPlugin::findBySQL("
                     (
                         name LIKE :likesearch
+                        OR pluginname LIKE :likesearch
                         OR (SELECT CONCAT(Vorname, ' ', Nachname) FROM auth_user_md5 WHERE user_id = pluginmarket_plugins.user_id LIMIT 1) LIKE :likesearch
                         OR MATCH (short_description, description) AGAINST (:search IN BOOLEAN MODE)
                         OR (SELECT GROUP_CONCAT(' ', tag) FROM pluginmarket_tags WHERE pluginmarket_tags.plugin_id = plugin_id GROUP BY pluginmarket_tags.plugin_id LIMIT 1) LIKE :likesearch
diff --git a/migrations/07_add_pluginname.php b/migrations/07_add_pluginname.php
new file mode 100644
index 0000000000000000000000000000000000000000..268b52586d402509608391867c4d0b48e7632ccb
--- /dev/null
+++ b/migrations/07_add_pluginname.php
@@ -0,0 +1,39 @@
+<?php
+class AddPluginname extends Migration {
+
+public function up() {
+
+    DBManager::get()->exec("
+    ALTER TABLE `pluginmarket_plugins` CHANGE `pluginclassname` `pluginname` VARCHAR(64) NOT NULL
+    ");
+    SimpleORMap::expireTableScheme();
+    foreach (MarketPlugin::findBySQL("1") as $plugin) {
+        if ($plugin->releases->count()) {
+            $pluginnames = array_count_values(array_filter($plugin->releases->getPluginName()));
+            arsort($pluginnames);
+            $pluginname = key($pluginnames);
+            if ($pluginname) {
+                $plugin->pluginname = $pluginname;
+
+                $plugin->releases->each(function ($one) use ($pluginname) {
+                    if ($one->getPluginName() != $pluginname) {
+                        $one->delete();
+                    }
+                });
+            } else {
+                $plugin->name .= " (no pluginname)";
+                $plugin->releases->delete();
+                $plugin->approved = 0;
+            }
+        } else {
+            $plugin->name .= " (no release)";
+            $plugin->approved = 0;
+        }
+        $plugin->store();
+    }
+}
+
+public function down() {
+}
+
+}
\ No newline at end of file
diff --git a/plugin.manifest b/plugin.manifest
index 01a4c73e6edfd25fda740945f5eb3a537aae179e..c903f4fefa4750350b9d6e19f0509ba629c8b40e 100755
--- a/plugin.manifest
+++ b/plugin.manifest
@@ -1,4 +1,4 @@
 pluginname=PluginMarktplatz
 pluginclassname=PluginMarket
 origin=studip
-version=1.0.15
+version=1.0.16
diff --git a/views/myplugins/edit.php b/views/myplugins/edit.php
index f2f932d3f66f13a279f75c7f0962c4a38305c681..67af53800f8a451c4598a60364aef1193e1b4c99 100755
--- a/views/myplugins/edit.php
+++ b/views/myplugins/edit.php
@@ -5,10 +5,13 @@
             <?= _("Informationen") ?>
         </legend>
         <label>
-            <?= _("Name des Plugins") ?>
-            <input type="text" name="data[name]" value="<?= htmlReady($marketplugin['name']) ?>">
+            <?= _("Angezeigter Name des Plugins") ?>
+            <input required type="text" name="data[name]" value="<?= htmlReady($marketplugin['name']) ?>">
+        </label>
+        <label>
+            <?= _("Interner Name des Plugins (aus dem Manifest)") ?>
+            <input required type="text" name="data[pluginname]" value="<?= htmlReady($marketplugin['pluginname']) ?>" <?=!$marketplugin->isNew() ? 'disabled' : ''?>>
         </label>
-
         <label>
             <?= _("Kurzbeschreibung") ?>
             <input type="text" name="data[short_description]" value="<?= htmlReady($marketplugin['short_description']) ?>" maxlength="160">
@@ -25,7 +28,7 @@
 
         <label>
             <?= _("Lange Beschreibung") ?>
-            <textarea class="add_toolbar" name="data[description]"><?= htmlReady($marketplugin['description']) ?></textarea>
+            <textarea class="wysiwyg" name="data[description]"><?= htmlReady($marketplugin['description']) ?></textarea>
         </label>
 
         <label>
diff --git a/views/myplugins/overview.php b/views/myplugins/overview.php
index d0d41e24a90e73993919c76dd66deadd972b399f..29ea77221ac1f07cc3d70d69513e3c59a5d1d9bc 100755
--- a/views/myplugins/overview.php
+++ b/views/myplugins/overview.php
@@ -66,7 +66,13 @@
 
     </tbody>
 </table>
-
+<? if ($edit_plugin_id = Request::option('edit_plugin_id')): ?>
+    <script>
+        jQuery(function ($) {
+            STUDIP.Dialog.fromURL('<?= $controller->url_for('myplugins/edit/' . $edit_plugin_id) ?>');
+        });
+    </script>
+<? endif; ?>
 <?
 $sidebar = Sidebar::Get();
 $sidebar->setImage(Assets::image_path("sidebar/plugin-sidebar.png"));
@@ -74,5 +80,14 @@ $actions = new ActionsWidget();
 $actions->addLink(_("Neues Plugin eintragen"),
     $controller->url_for('myplugins/add'),
     Icon::create('add'))->asDialog();
+$actions->addElement(new WidgetElement(
+        '<form action="' . $controller->url_for('myplugins/addfromzip') .'"
+      method="post" enctype="multipart/form-data" class="drag-and-drop">
+      <input type="hidden" name="release[type]" value="zipfile">
+    '. CSRFProtection::tokenTag() .'
+    '._('Plugin via Drag and Drop eintragen') .'
+    <input type="file" name="release_file">
+    </form>'
+));
 $sidebar->addWidget($actions);