Index: /controller/wpsg_BasketController.class.php
===================================================================
--- /controller/wpsg_BasketController.class.php	(revision 7000)
+++ /controller/wpsg_BasketController.class.php	(revision 7002)
@@ -90,7 +90,5 @@
 				
 			}
-			
-			
-			
+			 
 			// Zur Sicherheit ÃŒberprÃŒfe ich hier noch einmal die Zahlungsarten
 			// Es kann vorkommen, das eine Zahlungsart voreingestellt ist die nicht mehr verfÃŒgbar ist
@@ -114,4 +112,5 @@
 			if ($this->shop->hasMod('wpsg_mod_onepagecheckout') && ($this->get_option('wpsg_mod_onepagecheckout_basket') == 1))
 			{
+			    
 				$this->shop->view['arShipping'] = $this->shop->arShipping;
 				$this->shop->view['arPayment'] = $this->shop->arPayment;
@@ -124,4 +123,5 @@
 			else 
 			{
+			    
 				$content = $this->shop->render(WPSG_PATH_VIEW.'/warenkorb/basket.phtml', false);
 				
Index: /controller/wpsg_ShopController.class.php
===================================================================
--- /controller/wpsg_ShopController.class.php	(revision 7000)
+++ /controller/wpsg_ShopController.class.php	(revision 7002)
@@ -583,4 +583,34 @@
 		} // public function getURL($url_const, $entity = false)
 
+        /**
+         * Gibt den Pfad zurÃŒck, in dem der Shop seine Dateien ablegt
+         * Der Ordner wird fÃŒr direkte Zugriffe ÃŒber .htaccess gesperrt
+         */
+        public function getUplodatStoragePath() {
+
+            if ($this->isMultiBlog())
+            {
+ 
+                $path = WP_CONTENT_DIR.'/'.WPSG_MB_UPLOADS.'/wpsg/';
+
+            } else {
+
+                $path = WP_CONTENT_DIR.'/uploads/wpsg/';
+                
+            }
+
+            if (!file_exists($path.'.htaccess')) {
+
+                $handle = fopen($path.'.htaccess', 'w+');
+                $content = "Deny from all";
+                fwrite($handle, $content, strlen($content));
+                fclose($handle);
+
+            }
+
+            return $path;
+            
+        } // public function getUplodatStoragePath()
+        
 		/**
 		 * Checkt den Request und entfernt mÃ¶glicherweise escapte Variablen
Index: /lib/functions.inc.php
===================================================================
--- /lib/functions.inc.php	(revision 7000)
+++ /lib/functions.inc.php	(revision 7002)
@@ -436,10 +436,10 @@
 	 * Debug Funktion, die den ÃŒbergebenen Wert ausgibt wenn die Option im Backend aktiviert ist.
 	 */
-	function wpsg_debug($value)
+	function wpsg_debug($value, $small = false)
 	{
 		 
 		if ($GLOBALS['wpsg_sc']->get_option('wpsg_debugModus') != "1") return;
 		
-		echo '<pre style="color:red;">';
+		echo '<pre style="color:red; '.(($small === true)?'font-size:12px; overflow-x:scroll;':'').'">';
 		
 		if (is_array($value))
Index: /lib/helper_functions.inc.php
===================================================================
--- /lib/helper_functions.inc.php	(revision 7000)
+++ /lib/helper_functions.inc.php	(revision 7002)
@@ -46,5 +46,5 @@
 	
 		global $wp_filesystem;
-			
+			wpsg_debug($file);
 		// Datei existiert ÃŒberhaupt nicht und muss daher nicht gelÃ¶scht werden
 		if (!file_exists($file)) return;
@@ -69,23 +69,19 @@
 		{
 				
-			$dir_hdle = opendir($file);
-	
-			while ($subfile = readdir($dir_hdle))
-			{
-	
-				if (!in_array($subfile, array(".", "..")))
-				{
-	
-					$ok = wpsg_rrmdir($file."/".$subfile);
-					if (!$ok) return false;
-	
-				}
-			  
-			}
-	
-			closedir($dir_hdle);
-			 
+		    $arSubFiles = scandir($file);
+            
+            foreach ($arSubFiles as $subfile) {
+                
+                if (!in_array($subfile, ['.', '..'])) {
+
+                    $ok = wpsg_rrmdir($file."/".$subfile);
+                    if (!$ok) return false;
+                    
+                }
+                
+            }
+		    
 			$ok = @rmdir($file);
-				
+            
 			if (!$ok)
 			{
Index: /lib/wpsg_basket.class.php
===================================================================
--- /lib/wpsg_basket.class.php	(revision 7000)
+++ /lib/wpsg_basket.class.php	(revision 7002)
@@ -224,4 +224,7 @@
 
 			unset($_SESSION['wpsg']['basket'][$produkt_index]);
+            
+            $this->shop->callMods('basket_removeProduktFromSession', [$produkt_index]);
+            
 			$this->shop->cache->clearShopBasketArray();
 
Index: /lib/wpsg_exceptionhandler.class.php
===================================================================
--- /lib/wpsg_exceptionhandler.class.php	(revision 7000)
+++ /lib/wpsg_exceptionhandler.class.php	(revision 7002)
@@ -51,4 +51,9 @@
             ob_end_clean();
 
+            ob_start();
+            debug_print_backtrace();
+            $backtrace = ob_get_contents();
+            ob_end_clean();
+            
             $strLogText .= str_pad('', 120, '-')."\r\n";
 
@@ -58,5 +63,5 @@
             else file_put_contents($log_file, $strLogText);
 
-            die($typeLabel.": ".$msg);
+            die(wpsg_debug($typeLabel.": ".$msg."\r\n".$backtrace, true));
 
         } // static function myCallbackMethod($ex)
Index: /mods/wpsg_mod_basic.class.php
===================================================================
--- /mods/wpsg_mod_basic.class.php	(revision 7000)
+++ /mods/wpsg_mod_basic.class.php	(revision 7002)
@@ -325,8 +325,9 @@
 		/** PrÃŒft die Daten, die im Warenkorb erfasst sind auf ValiditÃ€t */
 		public function basket_check() { } // public function basket_check()
-		
-		/**
-		 * Wird nach dem Formular im basket.phtml aufgerufen
-		 */
+
+        /** Wird aufgerufen wenn ein Produkt aus dem Warenkorb entfernt wird */
+        public function basket_removeProduktFromSession($product_index) { } // public function basket_removeProduktFromSession($product_index)
+        
+		/** Wird nach dem Formular im basket.phtml aufgerufen */
 		public function basket_after(&$basket_view) { }
 		
Index: /mods/wpsg_mod_orderupload.class.php
===================================================================
--- /mods/wpsg_mod_orderupload.class.php	(revision 7000)
+++ /mods/wpsg_mod_orderupload.class.php	(revision 7002)
@@ -36,5 +36,17 @@
 			$this->shop->checkDefault('wpsg_mod_orderupload_multifiles', '0');
 			$this->shop->checkDefault('wpsg_mod_orderupload_optional', '0');
-			
+
+            require_once(WPSG_PATH_WP.'/wp-admin/includes/upgrade.php');
+
+            /**
+             * Produkttabelle erweitern
+             */
+            $sql = "CREATE TABLE ".WPSG_TBL_PRODUCTS." (
+		   		wpsg_mod_orderupload_set INT(11) NOT NULL,
+		   		wpsg_mod_orderupload_mandatory INT(1) NOT NULL
+		   	) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;";
+
+            dbDelta($sql);
+            
 		} // public function install()
 		
@@ -72,5 +84,5 @@
 			if ($state == '1')
 			{
-				
+			 
 				if (
 					$this->shop->get_option('wpsg_mod_orderupload_optional') != '1' && 
@@ -148,24 +160,53 @@
 			
 		} // public function checkCheckout(&$state, &$error, &$arCheckout)
-		
-		public function checkBasket(&$error) {
+         
+		public function checkBasket(&$noError) {
 			
 			$sum = 0;
-			if (wpsg_isSizedArray($_SESSION['wpsg']['wpsg_mod_orderupload']))
-			{
-				foreach ($_SESSION['wpsg']['wpsg_mod_orderupload'] as $k => $ou)
-				{
-					$sum += filesize($ou[3]);
-				}
-			}
+            
+			if (wpsg_isSizedArray($_SESSION['wpsg']['wpsg_mod_orderupload'])) {
+			    
+				foreach ($_SESSION['wpsg']['wpsg_mod_orderupload'] as $k => $ou) $sum += filesize($ou[3]);
+                
+			}
+			
 			$sum = $sum / (1024 * 1000);
 			$sum = $this->shop->get_option('wpsg_mod_orderupload_maxweight') - $sum;
-			if ($sum <= 0) {
-				$this->shop->addFrontendError(__($this->shop->get_option('wpsg_mod_orderupload_maxweight_text'), 'wpsg'));
-			}
+			
+            $text = __($this->shop->get_option('wpsg_mod_orderupload_maxweight_text'), 'wpsg');
+            
+            if ($sum <= 0 & wpsg_isSizedString($text)) { $this->shop->addFrontendError($text); $noError = false; }
 			
 			$this->shop->view['wpsg_mod_orderupload']['uploadsum'] = round($sum, 2);
 			$this->shop->view['wpsg_mod_orderupload']['maxweight'] = $this->shop->get_option('wpsg_mod_orderupload_maxweight');
 			
+            // Uploads bei den Produkten checken
+            $arBasket = $this->shop->cache->getShopBasketArray();
+            
+            foreach ($arBasket['produkte'] as $product_index => $product_basket_data) {
+                
+                $oProduct = wpsg_product::getInstance($product_basket_data['product_id']);
+                
+                $mandatory = $oProduct->wpsg_mod_orderupload_mandatory;
+                
+                if (wpsg_isSizedInt($mandatory)) {
+
+                    $set = $oProduct->wpsg_mod_orderupload_set;
+                    $arFilesUploaded = $this->getProductUploads($arBasket['oOrder']->id, $product_basket_data['product_index'], $product_basket_data['product_id']);
+                    
+                    if (sizeof($arFilesUploaded) < $set) {
+                        
+                        $this->shop->addFrontendError(
+                            wpsg_translate(__('Sie mÃŒssen bei Produkt "#1#" mindestens #2# Datei(en) angeben.', 'wpsg'), $oProduct->getProductName(), $set)
+                        );
+                        
+                        $noError = false;
+                        
+                    }
+                    
+                }
+                
+            }
+                        
 		}
 		
@@ -186,19 +227,34 @@
 			
 		} // public function wp_loaded()
-
-		public function order_ajax() 
-		{ 
-			
-			if (isset($_REQUEST['wpsg_mod_orderupload_download']))
-			{
-				
-				header('Content-Disposition: attachment; filename="'.rawurldecode($_REQUEST['wpsg_mod_orderupload_download']).'"');
-				header('Content-type: application/download');
-				header('Content-Disposition: inline; filename="'.rawurldecode($_REQUEST['wpsg_mod_orderupload_download']).'"');
-				header('Expires: 0');
-				header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
-				header('Pragma: public');
-				
-				die(file_get_contents($this->getSavePath($_REQUEST['edit_id']).'/'.rawurldecode($_REQUEST['wpsg_mod_orderupload_download'])));
+ 
+		public function order_ajax() { 
+			
+			if (isset($_REQUEST['wpsg_mod_orderupload_download'])) {
+								
+                if (isset($_REQUEST['product_index'])) {
+                    
+                    $path = $this->getProductStoragePath($_REQUEST['edit_id'], $_REQUEST['product_index']);
+                    $file = $path.$_REQUEST['wpsg_mod_orderupload_download'];
+                                        
+                } else {
+                
+				    $file = $this->getSavePath($_REQUEST['edit_id']).'/'.rawurldecode($_REQUEST['wpsg_mod_orderupload_download']);
+                                        
+                }
+                
+                if (!file_exists($file)) throw new \Exception(__('Datei existiert nicht mehr auf dem Server.', 'wpsg')); 
+                else {
+
+                    header('Content-Disposition: attachment; filename="'.rawurldecode($_REQUEST['wpsg_mod_orderupload_download']).'"');
+                    header('Content-type: application/download');
+                    header('Content-Disposition: inline; filename="'.rawurldecode($_REQUEST['wpsg_mod_orderupload_download']).'"');
+                    header('Expires: 0');
+                    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+                    header('Pragma: public');
+                    
+                    echo file_get_contents($file);
+                    exit;
+                    
+                }
 				
 			}
@@ -254,8 +310,144 @@
 			
 			wpsg_rrmdir($path);
-			
+			            
 		} // public function delOrder(&$order_id)
-		
+
+        public function product_addedit_content(&$product_content, &$product_data) {
+ 
+            if (isset($_REQUEST['wpsg_lang'])) return;
+
+            $this->shop->view['wpsg_mod_orderupload']['set'] = $product_data['wpsg_mod_orderupload_set'];
+            $this->shop->view['wpsg_mod_orderupload']['mandatory'] = $product_data['wpsg_mod_orderupload_mandatory'];
+            
+            $this->shop->view['arSubAction']['wpsg_mod_orderupload'] = array(
+                'title' => __('Bestellupload', 'wpsg'),
+                'content' => $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_orderupload/product_addedit_content.phtml', false)
+            );
+
+        } // public function produkt_edit_allgemein(&$produkt_data)
+ 
+        public function produkt_save_before(&$produkt_data) {  
+            
+            if (wpsg_isSizedArray($_REQUEST['wpsg_mod_orderupload'])) {
+                 
+                $produkt_data['wpsg_mod_orderupload_set'] = $_REQUEST['wpsg_mod_orderupload']['set'];
+                $produkt_data['wpsg_mod_orderupload_mandatory'] = $_REQUEST['wpsg_mod_orderupload']['mandatory'];
+                 
+            }
+            
+        } // public function produkt_save(&$produkt_id)
+
+        public function template_redirect() {
+
+            if (wpsg_isSizedString($_REQUEST['action'], 'wpsg_mod_orderupload_upload')) {
+                 
+                if ($_REQUEST['order_id'] != $_SESSION['wpsg']['order_id']) throw new \Exception(__('Zugriffsfehler!', 'wpsg'));
+                
+                $path = $this->getProductStoragePath($_REQUEST['order_id'], $_REQUEST['product_index']);
+                
+                $oProduct = wpsg_product::getInstance($_REQUEST['product_id']);
+                                
+                if (!$this->shop->hasFrontendError()) {
+                                        
+                    // Upload
+                    foreach ($_FILES['file']['tmp_name'] as $k => $f) {
+
+                        $arFilesUploaded = $this->getProductUploads($_REQUEST['order_id'], $_REQUEST['product_index']);
+                        if (sizeof($arFilesUploaded) >= $oProduct->wpsg_mod_orderupload_set) { $this->shop->addFrontendError(wpsg_translate(__('Sie haben die maximale Anzahl an Dateien (#1#) fÃŒr dieses Produkt erreicht.', 'wpsg'), $oProduct->wpsg_mod_orderupload_set)); break; }
+                        
+                        move_uploaded_file($f, $path.$_FILES['file']['name'][$k]); 
+                        
+                    }
+                    
+                }
+
+                echo $this->renderUploadTarget($_SESSION['wpsg']['order_id'], $_REQUEST['product_index'], $_REQUEST['product_id']); exit;
+                
+            } else if (wpsg_isSizedString($_REQUEST['action'], 'wpsg_mod_orderupload_delete')) {
+
+                if ($_REQUEST['order_id'] != $_SESSION['wpsg']['order_id']) throw new \Exception(__('Zugriffsfehler!', 'wpsg'));
+                
+                $path = $this->getProductStoragePath($_SESSION['wpsg']['order_id'], $_REQUEST['product_index']);
+                
+                if (file_exists($path.basename($_REQUEST['file']))) unlink($path.basename($_REQUEST['file']));
+                else $this->shop->addFrontendError(__('Datei konnte nicht gefunden werden.', 'wpsg'));
+                
+                echo $this->renderUploadTarget($_SESSION['wpsg']['order_id'], $_REQUEST['product_index'], $_REQUEST['product_id']); exit;
+                
+            }
+            
+        }
+
+        /** Wird aufgerufen wenn ein Produkt aus dem Warenkorb entfernt wird */
+        public function basket_removeProduktFromSession($product_index) { 
+            
+            $path = $this->getProductStoragePath($_SESSION['wpsg']['order_id'], $product_index);
+            $arFiles = $this->getProductUploads($_SESSION['wpsg']['order_id'], $product_index);
+            
+            foreach ($arFiles as $f) {
+                
+                @unlink($f);
+                
+            }
+            
+        } // public function basket_removeProduktFromSession($product_index)
+        
+        public function basket_row(&$p, $i) {  
+            
+            if (!wpsg_isSizedInt($p['wpsg_mod_orderupload_set'])) return false;
+
+            $this->shop->view['wpsg_mod_orderupload']['order_id'] = $_SESSION['wpsg']['order_id'];
+            $this->shop->view['wpsg_mod_orderupload']['product_id'] = $p['product_id'];
+            $this->shop->view['wpsg_mod_orderupload']['product_index'] = $p['product_index']; 
+            $this->shop->view['wpsg_mod_orderupload']['strHTMLTarget'] = $this->renderUploadTarget($_SESSION['wpsg']['order_id'], $p['product_index'], $p['product_id']);
+                         
+            $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_orderupload/basket_row.phtml');
+            
+        } // public function basket_row_afterproducts(&$p, $i)
+
+        public function basket_after(&$basket_view) {
+
+            $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_orderupload/basket_after.phtml');
+            
+        } // public function basket_after(&$basket_view)
+        
+        public function order_view_row(&$p, $i) { 
+            
+            $order_id = $this->shop->view['data']['id'];
+            $product_index = $p['product_index'];
+
+            $arUploadedFiles = $this->getProductUploads($order_id, $product_index);
+            
+            if (wpsg_isSizedArray($arUploadedFiles)) {
+
+                $arFileDownloadLinks = [];
+                
+                foreach ($arUploadedFiles as $f) {
+
+                    $arFileDownloadLinks[] = '<a target="_blank" href="'.WPSG_URL_WP.'wp-admin/admin.php?page=wpsg-Order&action=view&product_index='.$product_index.'&edit_id='.$order_id.'&noheader=1&action=ajax&mod=wpsg_mod_orderupload&wpsg_mod_orderupload_download='.rawurlencode(basename($f)).'">'.basename($f).'</a>';
+                }
+
+                $this->shop->view['wpsg_mod_orderupload']['arFileDownloadLinks'] = $arFileDownloadLinks;
+                $this->shop->view['wpsg_mod_orderupload']['arFiles'] = $arUploadedFiles;
+                $this->shop->view['wpsg_mod_orderupload']['i'] = $i;
+                $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_orderupload/order_view_row.phtml');
+                
+            } 
+            
+        } // public function order_view_row(&$p, $i)
+        
 		/* -- */
+		
+		private function renderUploadTarget($order_id, $product_index, $product_id) {
+
+            $this->shop->view['wpsg_mod_orderupload']['oProduct'] = wpsg_Product::getInstance($product_id);
+            $this->shop->view['wpsg_mod_orderupload']['order_id'] = $order_id;
+		    $this->shop->view['wpsg_mod_orderupload']['product_index'] = $product_index;
+            $this->shop->view['wpsg_mod_orderupload']['product_id'] = $product_id;
+            $this->shop->view['wpsg_mod_orderupload']['arFiles'] = $this->getProductUploads($order_id, $product_index);
+		    
+		    return $this->shop->render(WPSG_PATH_VIEW.'/mods/mod_orderupload/basket_row_upload_target.phtml', false);
+		     
+        } // private function renderUploadTarget($order_id, $product_index)
 		
 		public function getNewName($filename, $order_id)
@@ -312,4 +504,35 @@
  		} // public function getSavePath($order_id, $url = false)
 
+        /**
+         * Gibt den Pfad zurÃŒck, in dem die Dateien zu einer Bestellung/Produkt gespeichert sind
+         */
+        public function getProductStoragePath($order_id, $product_index) {
+
+            $path = $this->shop->getUplodatStoragePath().'wpsg_orderupload/'.$order_id.'/'.$product_index.'/';
+             
+            if (!file_exists($path)) mkdir($path, 0755, true);
+            
+            return $path;
+            
+        } // public function getProductStorage($order_id, $product_index)
+        
+        public function getProductUploads($order_id, $product_index) {
+            
+            $arFiles = [];
+            
+            $path = $this->getProductStoragePath($order_id, $product_index);
+            
+            foreach (scandir($path) as $file) {
+                
+                if (!in_array($file, ['.', '..']) && is_file($path.$file)) $arFiles[] = $path.$file;
+                
+            }
+            
+            asort($arFiles);
+            
+            return $arFiles;
+            
+        } // public function getProductUploads($order_id, $product_index)
+        
  		public function getAdminAttachment(&$attach)
  		{
@@ -322,12 +545,5 @@
 	 			foreach ($_SESSION['wpsg']['wpsg_mod_orderupload'] as $k => $ou)
 	 			{
-	 				/*
-	 				copy(
-	 						$ou[3],
-	 						$path.'/'.$this->getNewName($ou[0], $o_id)
-	 						);
-	 				unset($_SESSION['wpsg']['wpsg_mod_orderupload'][$k]);
-					*/
-	 				
+	 			    	 				
 	 				$attach[] = $path.$this->getNewName($ou[0], $o_id);
 	 				
@@ -335,26 +551,44 @@
 	 				
 	 			}
-
+	 			
+	 			$order_id = $this->shop->view['o_id'];
+                
+                foreach ($this->shop->view['basket']['produkte'] as $product_basket_data) {
+ 
+                    $arFilesUploaded = $this->getProductUploads($order_id, $product_basket_data['product_index'], $product_basket_data['product_id']);
+                    
+                    if (wpsg_isSizedArray($arFilesUploaded)) {
+
+                        foreach ($arFilesUploaded as $file) {
+                            
+                            $attach[] = $file;
+                            
+                        }
+
+                    }
+                    
+                } 
+                
  				if ($this->shop->get_option('wpsg_mod_orderupload_zip') == 1) {
  					
  					$zpath = $path.$this->getNewName('archiv', $o_id).'.zip';
- 					// Objekt erstellen und prÃŒfen, ob der Server zippen kann
+ 					
+                    // Objekt erstellen und prÃŒfen, ob der Server zippen kann
  					$zip = new ZipArchive();
- 					// ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE ÃŒberschreibt nicht das Archiv,
+ 					
+                    // ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE ÃŒberschreibt nicht das Archiv,
  					// deshalb die Archivdatei vorher lÃ¶schen
  					if (file_exists($zpath)) unlink($zpath);
  					
- 					if ($zip->open($zpath, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== TRUE) {
- 						die ("ERROR: Could not open archive");
- 					}
+ 					if ($zip->open($zpath, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== TRUE) { throw new \Exception("Could not open archive"); }
  					
  					foreach ($attach as $k => $v) {
  						
  						$vl = pathinfo($v);
- 						$zip->addFile($v, $vl['basename']) or die ("ERROR: Could not add file: $v");
+ 						$zip->addFile($v, $vl['basename']);
+                        
  					}
 
  					// Zip-Datei speichern
- 					$anz = $zip->numFiles;
  					$zip->close();
  					
@@ -363,4 +597,5 @@
  					
  				}
+ 				
  			}
  			
@@ -368,5 +603,2 @@
  		
 	} // class wpsg_mod_orderupload extends wpsg_mod_basic
-
-
-?>
Index: /views/css/frontend.css
===================================================================
--- /views/css/frontend.css	(revision 7000)
+++ /views/css/frontend.css	(revision 7002)
@@ -38,4 +38,10 @@
 .basket_product_wrap .basket_product_row .product_action .price_total { width: 39%; display:inline-block; font-weight:bold; text-align:right; }
 .basket_product_wrap .basket_product_row .product_info { display:flex; width:100%; justify-content:space-between; align-items:center; }
+.basket_product_wrap .basket_product_row .product_upload {  }
+.basket_product_wrap .basket_product_row .product_upload .wpsg_mod_orderupload_target { margin-left:15px; flex-grow:1; }
+.basket_product_wrap .basket_product_row .product_upload .wpsg_mod_orderupload_target ul { margin:0px; }
+.basket_product_wrap .basket_product_row .product_upload .wpsg_mod_orderupload_target li { display:flex; justify-content:space-between; }
+.basket_product_wrap .basket_product_row .product_upload .wpsg_mod_orderupload_target li a.removeLink { text-decoration:none; box-shadow:none; align-self:center; }
+.basket_product_wrap .basket_product_row .product_upload ul li { list-style:none; }
 .basket_product_wrap .basket_product_row .product_info .titlep { min-width:120px; display:inline-block; margin-top:0.3em; margin-bottom:0.3em; }
 .basket_product_wrap .basket_product_row .product_info .title { width: 30%; display:inline-block; margin-top:0.3em; margin-bottom:0.3em; }
Index: /views/mods/mod_orderupload/basket_after.phtml
===================================================================
--- /views/mods/mod_orderupload/basket_after.phtml	(revision 7002)
+++ /views/mods/mod_orderupload/basket_after.phtml	(revision 7002)
@@ -0,0 +1,81 @@
+<?php
+    
+    /**
+     * User: Daschmi (daschmi@daschmi.de)
+     * Date: 02.05.2018
+     * Time: 10:47
+     */
+    
+?>
+
+<script>
+
+    function wpsg_mod_orderupload_upload(product_index, product_id) {
+ 
+        var files = document.getElementById('wpsg_mod_orderupload_' + product_index + '_file').files;
+        var formData = new FormData();
+
+        for (var i = 0; i < files.length; i++) {
+
+            var file = files[i];
+
+            formData.append('file[]', file, file.name);
+
+        }
+
+        formData.append('product_index', product_index);
+        formData.append('product_id', product_id);
+        formData.append('order_id', '<?php echo $_SESSION['wpsg']['order_id']; ?>'); 
+        formData.append('action', 'wpsg_mod_orderupload_upload');
+
+        var xhr = new XMLHttpRequest();
+
+        xhr.open('POST', wpsg_ajax.ajaxurl, true);
+
+        jQuery('#wpsg_mod_orderupload_' + product_index + '_target').html('<?php echo __('Bitte warten ', 'wpsg'); ?><img src="' + wpsg_ajax.img_ajaxloading + '" alt="' + wpsg_ajax.label_pleasewait + '" /></div>');
+
+        xhr.onload = function () {
+
+            if (xhr.status === 200) {
+
+                jQuery('#wpsg_mod_orderupload_' + product_index + '_target').html(xhr.responseText);
+
+            } else {
+
+                alert("<?php echo __('Fehler', 'wpsg'); ?>: " + xhr.responseText);
+
+            }
+
+        };
+
+        xhr.send(formData);
+
+        return false;
+        
+    }
+    
+    function wpsg_mod_orderupload_removefile(file, product_index, product_id) {
+                         
+        jQuery('#wpsg_mod_orderupload_' + product_index + '_target').html('<?php echo __('Bitte warten ', 'wpsg'); ?><img src="' + wpsg_ajax.img_ajaxloading + '" alt="' + wpsg_ajax.label_pleasewait + '" /></div>');
+        
+        jQuery.ajax( {
+            url: wpsg_ajax.ajaxurl,
+            data: {
+                action: 'wpsg_mod_orderupload_delete',
+                order_id: <?php echo $_SESSION['wpsg']['order_id'] ?>,
+                product_index: product_index,
+                product_id: product_id,
+                file: file
+            }, 
+            success: function(data) {
+
+                jQuery('#wpsg_mod_orderupload_' + product_index + '_target').html(data);
+                
+            }
+        } );
+        
+        return false;
+        
+    } // wpsg_mod_orderupload_removefile(aElement)
+    
+</script>
Index: /views/mods/mod_orderupload/basket_row.phtml
===================================================================
--- /views/mods/mod_orderupload/basket_row.phtml	(revision 7000)
+++ /views/mods/mod_orderupload/basket_row.phtml	(revision 7002)
@@ -6,48 +6,13 @@
 
 ?>
-<div class="wpsg_box wpsg_mod_orderupload">
+<div class="product_info product_upload">
 
-	<div class="wpsg_head"><?php echo __('Dateiupload:', 'wpsg'); ?> 
-		
-		<?php if ($this->get_option('wpsg_mod_orderupload_optional') != '1') { ?>
-		
-			<span class="wpsg_required">*</span>
-			
-		<?php } ?>
-		
+	<?php echo __('Upload zum Produkt', 'wpsg'); ?>:
+	
+	<div id="wpsg_mod_orderupload_<?php echo $this->view['wpsg_mod_orderupload']['product_index']; ?>_target" class="wpsg_mod_orderupload_target">
+
+		<?php echo $this->view['wpsg_mod_orderupload']['strHTMLTarget']; ?>
+				
 	</div>
-	
-	<div class="wpsg_inner">
-			
-		<?php if ($this->view['wpsg_mod_orderupload']['uploadsum'] > 0) { ?>
-			<input class="wpsg_orderupload_checkout_button" type="file" name="wpsg_mod_orderupload_file" />
- 		<?php } ?>
- 
- 		<?php /* Auflistung der bereits hochgeladenen Dokumente */ ?>
-		<?php if (wpsg_isSizedArray($_SESSION['wpsg']['wpsg_mod_orderupload'])) { ?>
-		
-			<br />
-			
-			<label class="wpsg_checkout"><?php echo __('Bisher hochgeladene Dokumente', 'wpsg'); ?>:</label><br />
-			
-			<?php foreach ($_SESSION['wpsg']['wpsg_mod_orderupload'] as $ou_index => $ou) { ?>
-			
-				<?php /* Dokument aus der Liste lÃ¶schen */ ?>
-				<a onclick="return confirm('<?php echo __('Sind Sie sich sicher, dass Sie dieses Dokument aus der Bestellung entfernen mÃ¶chten?', 'wpsg'); ?>');" href="?wpsg_plugin=wpsg_mod_orderupload&wpsg_action=remove&file_index=<?php echo $ou_index; ?>" class="wpsg_mod_orderupload_removelink">
-					<img src="<?php echo WPSG_URL; ?>views/gfx/bin_x.png" alt="<?php echo __('LÃ¶schen', 'wpsg'); ?>" />
-				</a>
-				
-				<a href="<?php echo $ou[2]; ?>"><?php echo wpsg_hspc($ou[0]); ?></a>&nbsp;<?php echo '('.wpsg_formatSize($ou[3]).')'; ?><br />	
-					
-			<?php } ?>
-			
-		<?php } ?>
-			
-	</div>
-	
-	<?php /* Counter, wie viel MB noch ÃŒbrig sind */?>
-	<label class="wpsg_fileweight">
-		<?php echo wpsg_translate(__('Es stehen Ihnen #1# Mb von #2# Mb fÃŒr den Upload zur VerfÃŒgung', 'wpsg'), $this->view['wpsg_mod_orderupload']['uploadsum'],$this->view['wpsg_mod_orderupload']['maxweight']);?>
-	</label>
-	
+	 	
 </div>
Index: /views/mods/mod_orderupload/basket_row_upload_target.phtml
===================================================================
--- /views/mods/mod_orderupload/basket_row_upload_target.phtml	(revision 7002)
+++ /views/mods/mod_orderupload/basket_row_upload_target.phtml	(revision 7002)
@@ -0,0 +1,30 @@
+<?php echo $this->writeFrontendMessage(); ?>
+
+<?php if (wpsg_isSizedArray($this->view['wpsg_mod_orderupload']['arFiles'])) { ?>
+
+    <ul>
+        
+        <?php foreach ($this->view['wpsg_mod_orderupload']['arFiles'] as $f) { ?>
+        
+            <li>
+                
+                <a href=""><?php echo basename($f); ?> <span class="size">(<?php echo wpsg_formatSize($f); ?>)</span></a>
+                
+                <a title="<?php echo __('Upload entfernen.', 'wpsg'); ?>" class="removeLink" onclick="return wpsg_mod_orderupload_removefile('<?php echo rawurlencode(basename($f)); ?>', <?php echo $this->view['wpsg_mod_orderupload']['product_index']; ?>, <?php echo $this->view['wpsg_mod_orderupload']['product_id']; ?>);" href="#">
+                    <img src="<?php echo WPSG_URL; ?>views/gfx/bin_x.png" alt="<?php echo __('LÃ¶schen', 'wpsg'); ?>" />
+                </a>
+                
+            </li>
+    
+        <?php } ?>
+
+    </ul>
+    
+<?php } ?>
+
+<?php if ($this->view['wpsg_mod_orderupload']['oProduct']->wpsg_mod_orderupload_set > sizeof($this->view['wpsg_mod_orderupload']['arFiles'])) { ?>
+
+    <input type="file" id="wpsg_mod_orderupload_<?php echo $this->view['wpsg_mod_orderupload']['product_index']; ?>_file" name="wpsg_mod_orderupload[<?php echo $this->view['wpsg_mod_orderupload']['product_index']; ?>]" multiple="multiple" />
+    <input type="button" onclick="return wpsg_mod_orderupload_upload(<?php echo $this->view['wpsg_mod_orderupload']['product_index']; ?>, <?php echo $this->view['wpsg_mod_orderupload']['product_id']; ?>);" id="wpsg_mod_orderupload_<?php echo $this->view['wpsg_mod_orderupload']['product_index']; ?>_button" value="<?php echo __('Hochladen', 'wpsg'); ?>" />
+
+<?php } ?>
Index: /views/mods/mod_orderupload/order_view_row.phtml
===================================================================
--- /views/mods/mod_orderupload/order_view_row.phtml	(revision 7002)
+++ /views/mods/mod_orderupload/order_view_row.phtml	(revision 7002)
@@ -0,0 +1,16 @@
+<?php
+
+    /**
+     * Template fÃŒr die Integration des Produktuploads in die Bestellverwaltung Reiter "Bestelldaten"
+     */
+
+    $view = $this->view['wpsg_mod_orderupload'];
+    
+?>
+<tr class="wpsg_<?php echo (($view['i'] == 0)?'odd':'even'); ?>">
+    <td align="left" colspan="<?php echo ((sizeof($this->view['basket']['mwst']) > 1 || $this->get_option('wpsg_showMwstAlways') == '1')?'5':'4'); ?>">
+        <label>
+            <?php echo wpsg_translate(__('Produktuploads: #1#', 'wpsg'), implode(', ', $view['arFileDownloadLinks'])); ?>
+        </label>
+    </td>
+</tr>
Index: /views/mods/mod_orderupload/product_addedit_content.phtml
===================================================================
--- /views/mods/mod_orderupload/product_addedit_content.phtml	(revision 7002)
+++ /views/mods/mod_orderupload/product_addedit_content.phtml	(revision 7002)
@@ -0,0 +1,45 @@
+<?php
+    
+    /**
+     * User: Daschmi (daschmi@daschmi.de)
+     * Date: 02.05.2018
+     * Time: 07:25
+     */
+
+?>
+    
+<?php echo wpsg_drawForm_AdminboxStart(__('Bestellupload', 'wpsg')); ?>
+
+    <?php echo wpsg_drawForm_Checkbox('wpsg_mod_orderupload_set', __('Bestellupload ermÃ¶glichen'), (($this->view['wpsg_mod_orderupload']['set'] > 0)?true:false)); ?>
+
+    <div class="wpsg_mod_orderupload_set_1" style="<?php echo (($this->view['wpsg_mod_orderupload']['set'] > 0)?'display:block;':'display:none;'); ?>">
+
+        <?php echo wpsg_drawForm_Input('wpsg_mod_orderupload[set]', __('Maximale Anzahl an Uploads'), $this->view['wpsg_mod_orderupload']['set']); ?>
+        <?php echo wpsg_drawForm_Checkbox('wpsg_mod_orderupload[mandatory]', __('Pflichtfeld'), $this->view['wpsg_mod_orderupload']['mandatory']); ?>
+        
+    </div>    
+
+    <script>
+        
+        jQuery(document).ready(function() {
+            
+            jQuery('#wpsg_mod_orderupload_set').on('change', function() {
+                
+                if (jQuery(this).prop('checked') === true) {
+                    
+                    jQuery('.wpsg_mod_orderupload_set_1').show();
+                    jQuery('#wpsg_mod_orderuploadset').focus();
+                    
+                } else {
+
+                    jQuery('.wpsg_mod_orderupload_set_1').hide();
+                    
+                }
+                
+            } ).change();
+            
+        } );
+        
+    </script>
+
+<?php echo wpsg_drawForm_AdminboxEnd(); ?>  
Index: /views/warenkorb/basket.phtml
===================================================================
--- /views/warenkorb/basket.phtml	(revision 7000)
+++ /views/warenkorb/basket.phtml	(revision 7002)
@@ -29,5 +29,5 @@
 
 	<?php if (!isset($this->view['noFormTag'])) { ?>
-	<form id="wpsg_basket_form" name="wpsg_basket_form"  method="post" action="<?php echo $this->getURL(wpsg_ShopController::URL_CHECKOUT); ?>">
+	<form id="wpsg_basket_form" name="wpsg_basket_form"  method="post" action="<?php echo $this->getURL(wpsg_ShopController::URL_CHECKOUT); ?>" enctype="multipart/form-data">
 	<?php } ?>
 
