We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 15082
    • 195 Posts
    OK folks,

    I’ve done a quick and dirty patching of the filedownload.class.inc.php.
    This was ONLY for getting the filedownload working with german umlauts in my single scenario.
    Especially I dont use multiple download folders and therefore have not tweaked the script to handle these too.

    On my install it’s working with umlauts in file and folder names.

    I don’t know if it’s important for someone to know... but I’m using the script with the filedownload plugin.

    As I’m not a PHP guru, I’ve done a quick and dirty patch, that is working for my needs.
    Anyway, I want to give something back to the community and maybe it can be useful for someone. Or be the starting point of adding special characters support to the script.

    The whole patched filedownload.class.inc.php follows.

    <?php
    /**********************************
    FileDownload Class (v2.6)
    Created By: Kyle Jaebker
    Modified By: 
    Adam Strzelecki - 11/18/2006
    Adam Strzelecki - 01/02/2007
    Kyle Jaebker - 01/02/2007
    Kyle Jaebker - 09/08/2007
    **********************************/
    
    include_once "data.db.class.inc.php";
    
    //jusi add: performing urlencode, leaving slashes alone
    function jURLencode($inputString) {
    		$outputString = str_replace('%2F','/',rawurlencode($inputString));
    		return $outputString;
    }
    //end jusi
    
    class FileDownload {
    	var $_parameters = array();
    	var $_templates = array();
    	var $_config = array();
    	var $_lang = array();
    	var $allFiles = array();
    	var $fcounts = array();
    	var $urlSetting;
    	var $db;
    
    	function FileDownload() {
    		$this->db = new FdDataDb;
    	}
    
    	function Run() {
    		global $modx;
    		$output = '';
    
    		//Language string settings
    		$this->_lang['delSuccess'] = !is_null($this->Get('delSuccess')) ? $this->Get('delSuccess') : 'You have deleted: ';
    		$this->_lang['delError'] = !is_null($this->Get('delError')) ? $this->Get('delError') : 'There was an error deleting: ';
    		$this->_lang['dirOpenError'] = !is_null($this->Get('dirOpenError')) ? $this->Get('dirOpenError') : 'Cannot open the directory: ';
    		$this->_lang['notaDir'] = !is_null($this->Get('notaDir')) ? $this->Get('notaDir') : 'The path specified is not a directory: ';
    		$this->_lang['noDownload'] = !is_null($this->Get('noDownload')) ? $this->Get('noDownload') : 'You do not have permission to download this file.';
    
    		// Check for first run if DB count
    		$this->_config['useDbCount'] = !is_null($this->Get('useDbCount')) ? $this->Get('useDbCount') : 1;
    		$this->_config['skipTableCheck'] = !is_null($this->Get('skipTableCheck')) ? $this->Get('skipTableCheck') : 0;
    		if ($this->_config['useDbCount'] && !$this->_config['skipTableCheck']) {
    			$this->db->firstRun($this->db->config['fdTable']);
    		}
    		
    		//Set date format
    		$this->_config['dateFormat'] = !is_null($this->Get('dateFormat')) ? $this->Get('dateFormat') : 'Y-m-d';
    
    		// Check for FileDownloadPlugin
    		$this->_config['usePlugin'] = !is_null($this->Get('usePlugin')) ? $this->Get('usePlugin') : 0;
    
    		//Get url config settings
    		$this->_config['urlsetting'] = $modx->config['friendly_urls'] ? '?' : '&' ;
    		$this->_config['curUrl'] = $modx->makeURL($modx->documentIdentifier);
    
    		//Style Settings
    		$this->_config['css']['alt'] = !is_null($this->Get('altCss')) ? $this->Get('altCss') : 'fd-alt';
    		$this->_config['css']['firstFolder'] = !is_null($this->Get('firstFolderCss')) ? $this->Get('firstFolderCss') : '';
    		$this->_config['css']['lastFolder'] = !is_null($this->Get('lastFolderCss')) ? $this->Get('lastFolderCss') : '';
    		$this->_config['css']['firstFile'] = !is_null($this->Get('firstFileCss')) ? $this->Get('firstFileCss') : '';
    		$this->_config['css']['lastFile'] = !is_null($this->Get('lastFileCss')) ? $this->Get('lastFileCss') : '';
    		$this->_config['css']['folder'] = !is_null($this->Get('folderCss')) ? $this->Get('folderCss') : 'fd-folder';
    		$this->_config['css']['file'] = !is_null($this->Get('fileCss')) ? $this->Get('fileCss') : 'fd-file';
    		$this->_config['css']['parent'] = !is_null($this->Get('parentCss')) ? $this->Get('parentCss') : 'fd-parent';
    		$this->_config['css']['directory'] = !is_null($this->Get('directoryCss')) ? $this->Get('directoryCss') : 'fd-directory';
    		$this->_config['css']['path'] = !is_null($this->Get('pathCss')) ? $this->Get('pathCss') : 'fd-path';
    		$this->_config['css']['extension'] = !is_null($this->Get('extCss')) ? $this->Get('extCss') : 0;
    
    		//Image Settings
    		$this->_config['imgLocat'] = !is_null($this->Get('imgLocat')) ? $this->Get('imgLocat') : '';
    		if(!is_null($this->Get('imgTypes'))) {
    			$imageChunk = $modx->getChunk($this->Get('imgTypes'));
    			if($imageChunk) {
    				$imageChunk = explode(',',$imageChunk);
    				$fdImages = array();
    				foreach ($imageChunk as $n => $v) {
    					$tempImage = explode('=',trim($v));
    					$fdImages[$tempImage[0]] = $tempImage[1];
    				}
    				$this->_config['imgTypes'] = $fdImages;
    			} else {
    				$this->_config['imgTypes'] = 0;
    			}
    		}
    
    		//Check if multiple folders specified
    		if (strpos($this->Get('getFolder'),',')) {
    			$this->_config['getFolder'] = explode(',',$this->Get('getFolder'));
    			$this->_config['multiFolders'] = 1;
    		} else {
    			$this->_config['getFolder'] = $this->Get('getFolder');
    			$this->_config['multiFolders'] = 0;
    		}
    
    		//Check if file description chunks specified
    		if(!is_null($this->Get('chkDesc'))) {
    			$descriptChunk = $modx->getChunk($this->Get('chkDesc'));
    			if($descriptChunk) {
    				$this->_config['chkDesc'] = $descriptChunk;
    			} else {
    				$this->_config['chkDesc'] = 0;
    			}
    		}
    
    		//If single file downloading is specified
    		$this->_config['getFile'] = !is_null($this->Get('getFile')) ? $this->Get('getFile') : 0;
    
    		//File extension filter settings
    		$this->_config['showExt'] = is_null($this->Get('showExt')) ? 0 : explode(',',$this->Get('showExt'));
    		$this->_config['hideExt'] = is_null($this->Get('hideExt')) ? 0 : explode(',',$this->Get('hideExt'));
    		$this->_config['filterExt'] = ($this->_config['showExt'] || $this->_config['hideExt']) ? 1 : 0;
    
    		//Get Permissions
    		$this->_config['canDownload'] = !is_null($this->Get('downloadGroups')) ? $modx->isMemberOfWebGroup(explode(',', $this->Get('downloadGroups'))) : 1;
    		$this->_config['canDelete'] = !is_null($this->Get('deleteGroups')) ? $modx->isMemberOfWebGroup(explode(',', $this->Get('deleteGroups'))) : 0;
    
    		//Setup Directory Browsing
    		$this->_config['browseDirectories'] = !is_null($this->Get('browseDirectories')) && !$this->_config['multiFolders'] ? 1 : 0;
    		if ($this->_config['browseDirectories']) {
    			// Just for safety, directory traversal should not be possible
    			$badPath = array('../','/../','/..');
    			//$relPath = str_replace($badPath, '', $_GET['relPath']);
    			$relPath = str_replace($badPath, '', rawurldecode($_GET['relPath'])); //jusi: changed, original above
    			$this->_config['getFolder'] .= $relPath ? '/' . $relPath : '';
    			//jusi: added for urlencoding
    			$relPath = jURLencode($relPath);
    			//end jusi
    			$this->_config['curRelPath'] = $relPath;
    		}
    
    		//Location of files for download count & download processing
    		$this->_config['fileCount'] = 'assets/snippets/filedownload/filecount.txt';
    
    		//Setup download counting
    		$this->_config['countDownloads'] = !is_null($this->Get('countDownloads')) ? $this->Get('countDownloads') : 1;
    		if ($this->_config['countDownloads'] && $this->_config['usePlugin']) {
    			$this->loadCounts();
    			$this->_config['countDownloads'] = 1;
    		} else {
    			$this->_config['downloadCount'] = 0;
    			$this->_config['countDownloads'] = 0;
    		}
    
    		//Get the files into an array
    		if ($this->_config['multiFolders']) {
    			foreach ($this->_config['getFolder'] as $nFolder => $aFolder) {
    				if (is_array($this->getFiles($aFolder,$nFolder))) {
    					$this->allFiles = array_merge($this->allFiles,$this->getFiles($aFolder,$nFolder));
    				}
    			}
    		} else {
    			$this->allFiles = array_merge($this->allFiles,$this->getFiles($this->_config['getFolder']));
    		}
    
    		//Delete file if delete link clicked
    		if ($this->_config['canDelete'] && isset($_GET['act'])) {
    			$output .= $this->deleteFile();
    		}
    
    		//Sorting the array of files
    		if ($this->_config['browseDirectories']) {
    			$this->_config['userSort'] = 'type,';
    			$this->_config['userSort'] .= !is_null($this->Get('userSort')) ? $this->Get('userSort') : 'filename';
    			$this->_config['sortOrder'] = 'asc';
    		} else {
    			$this->_config['groupByDirectory'] = !is_null($this->Get('groupByDirectory')) ? $this->Get('groupByDirectory') : 0;
    			$this->_config['userSort'] = $this->_config['groupByDirectory'] ? 'path,' : '';
    			$this->_config['userSort'] .= !is_null($this->Get('userSort')) ? $this->Get('userSort') : 'filename';
    			$this->_config['sortOrder'] = !is_null($this->Get('sortOrder')) ? $this->Get('sortOrder') : 'asc';
    		}
    		$this->customSort($this->allFiles, $this->_config['userSort'], $this->_config['sortOrder']);
    
    		//Get the Templates
    		$this->_config['splitter'] = !is_null($this->Get('splitter')) ? $this->Get('splitter') : '<!-- Fd:Splitter -->';
    
    		if($this->Get('tplList')) $this->_templates['orig'] = $modx->getChunk($this->Get('tplList'));
    		if(empty($this->_templates['orig'])) $this->_templates['orig'] = $this->getDefaultLayout();
    
    		$this->_templates['parts'] = $this->getTemplateArray($this->_templates['orig'],$this->_config['splitter']);
    
    		//Create the output
    		$output .= $this->generateOutput();
    		return $output;
    	}
    
    	function Get($field) {
    		return $this->_parameters[$field];
    	}
    
    	function Set($field, $value) {
    		$this->_parameters[$field] = $value;
    	}
    
    	function generateOutput() {
    		//Setup Placeholders
    		$placeholders = array('[+fd.filename+]','[+fd.extension+]','[+fd.path+]','[+fd.size+]','[+fd.sizetext+]','[+fd.type+]','[+fd.date+]','[+fd.description+]','[+fd.image+]','[+fd.delete+]','[+fd.count+]','[+fd.link+]','[+fd.class+]','[+fd.filenumber+]');
    
    		$alt = 0;
    
    		$output = $this->_templates['parts']['header'];
    		// Add the path for browse directories & up level link
    		if ($this->_config['browseDirectories']) {
    			$pathPlaceholders = array('[+fd.path+]','[+fd.class+]');
    			$curRelPath = $this->_config['curRelPath'] ? '/'.$this->_config['curRelPath'] : '/';
    			$pathClass = $this->setClass('path',$alt);
    			//$values = array($curRelPath,$pathClass);
    			$values = array(htmlentities(rawurldecode($curRelPath)),$pathClass); //jusi: changed, original above
    			$output = str_replace($pathPlaceholders,$values,$output);
    			$alt = $alt ? 0 : 1;
    
    			if ($this->_config['curRelPath']) {
    				$rowOutput = $this->_templates['parts']['parent'];
    				$relPathParts = explode('/', $this->_config['curRelPath']);
    				array_pop($relPathParts);
    				$parentLink = $this->createLink(1,'',implode('/', $relPathParts),1);
    				$parentImage = $this->_config['imgTypes'] ? $this->selectImage('parent') : '';
    				$parentClass = $this->setClass('parent',$alt);
    				$values = array('../','','','','-','dir','','',$parentImage,'','',$parentLink,$parentClass);
    				$rowOutput = str_replace($placeholders, $values, $rowOutput);
    				$output .= $rowOutput;
    				$alt = $alt ? 0 : 1;
    			}
    		}
    
    		$alt = $alt ? 0 : 1;
    		$prevDir = '';
    		$fileTotal = 0;
    		$dirTotal = 0;
    
    		foreach ($this->allFiles as $n=>$v) {
    			if ($this->_config['groupByDirectory'] && $v['path'] !== $prevDir) {
    				$dirOutput = $this->_templates['parts']['directory'];
    				$dirPlaceholders = array('[+fd.directory+]','[+fd.class+]');
    				$dirClass = $this->setClass('multidir',$alt);
    				$values = array($v['path'],$dirClass);
    				$dirOutput = str_replace($dirPlaceholders,$values,$dirOutput);
    				$output .= $dirOutput;
    				$alt = $alt ? 0 : 1;
    			}
    			if ($v['path'] !== $prevDir) {
    				$fileTotal = $this->fcounts[$v['path']]['files'];
    				$dirTotal = $this->fcounts[$v['path']]['dirs'];
    				$dirCount = 1;
    				$fileCount = 1;
    			}
    			if ($v['type'] == 'dir') {
    				$rowOutput = $this->_templates['parts']['folder'];
    				$first = ($dirCount == 1) ? 1 : 0;
    				$last = ($dirCount == $dirTotal) ? 1 : 0;
    				$dirCount++;
    			} else {
    				$rowOutput = $this->_templates['parts']['row'];
    				$first = ($fileCount == 1) ? 1 : 0;
    				$last = ($fileCount == $fileTotal) ? 1 : 0;
    				$fileCount++;
    			}
    			if ($this->_config['canDelete']) {
    				$delRelPath = $this->_config['curRelPath'] ? ('&relPath=' . $this->_config['curRelPath']) : '';
    				$deleteLink = $this->_config['curUrl'] . $this->_config['urlsetting'] . 'act=' . $v['delete'] . $delRelPath;
    				$v['delete'] = $this->_templates['parts']['delete'];
    				$v['delete'] = str_replace('[+fd.deletelink+]',$deleteLink,$v['delete']);
    			} else {
    				$v['delete'] = '';
    			}
    			$values = array_values($v);
    			$values['class'] = $this->setClass($v['type'],$alt,$first,$last,$v['extension']);
    			$values['filenumber'] = ($v['type'] == 'dir') ? $dirCount-1 : $fileCount-1 ;
    			$rowOutput = str_replace($placeholders, $values, $rowOutput);
    			$output .= $rowOutput;
    
    			$prevDir = $v['path'];
    			$alt = $alt ? 0 : 1;
    		}
    		$output .= $this->_templates['parts']['footer'];
    		return $output;
    	}
    
    	function validExtension($extension) {
    		if ($this->_config['showExt']) {
    			$validExt = FALSE;
    			foreach ($this->_config['showExt'] as $showExt) {
    				if (!(strpos($showExt,$extension) === FALSE)) {
    					$validExt = TRUE;
    					break;
    				}
    			}
    		} else if ($this->_config['hideExt']) {
    			$validExt = TRUE;
    			foreach ($this->_config['hideExt'] as $hideExt) {
    				if (!(strpos($hideExt,$extension) === FALSE)) {
    					$validExt = FALSE;
    					break;
    				}
    			}
    		}
    		if ($validExt === FALSE) {
    			return 0;
    		} else {
    			return 1;
    		}
    	}
    
    	function fileSizeText($fileSize) {
    		if ($fileSize == 0) $returnVal = '0 bytes';
    		else if ($fileSize > 1024*1024*1024) $returnVal = (ceil($fileSize/(1024*1024*1024)*100)/100) . ' GB';
    		else if ($fileSize > 1024*1024) $returnVal = (ceil($fileSize/(1024*1024)*100)/100) . ' MB';
    		else if ($fileSize > 1024) $returnVal = (ceil($fileSize/1024*100)/100) . ' kB';
    		else $returnVal = $fileSize . ' B';
    		return $returnVal;
    	}
    
    	function selectImage($extension) {
    		if (array_key_exists($extension,$this->_config['imgTypes'])) {
    			$image = $this->_config['imgTypes'][$extension];
    		} else {
    			$image = $this->_config['imgTypes']['default'];
    		}
    		return $this->_config['imgLocat'] . '/' . $image;
    	}
    
    	function getDescription($filename) {
    		$filename = str_replace('/','\/',$filename);
    		$filename = str_replace('.','\.',$filename);
    		$pattern = '/' . $filename . '\|(.*?)' . '\|{2}/';
    		preg_match($pattern,$this->_config['chkDesc'],$result);
    		return $result[1];
    	}
    
    	function getDownloadCount($filename) {
    		if (array_key_exists($filename,$this->_config['downloadCount'])) {
    			$dwnCount = $this->_config['downloadCount'][$filename];
    		} else {
    			$dwnCount = 0;
    		}
    		return $dwnCount;
    	}
    
    	function createLink($isDir,$filelocat,$filename,$isParent=0,$fileSize=0,$multiFolderNum=0) {
    		if ($isDir) {
    			$fileLink = $this->_config['curUrl'] . $this->_config['urlsetting'] . 'relPath=' ;
    			if ($isParent) {
    				if ($filename) {
    					//$fileLink .= $filename;
    					$fileLink .= jURLencode($filename); //jusi: changed, original above
    				} else {
    					//$fileLink = $this->_config['curUrl'];
    					$fileLink = jURLencode($this->_config['curUrl']); //jusi: changed, original above
    				}				
    			} else {
    				//$fileLink .= $this->_config['curRelPath'] ? $this->_config['curRelPath'] . '/' . $filename : $filename;
    				$fileLink .= $this->_config['curRelPath'] ? $this->_config['curRelPath'] . '/' . jURLencode($filename) : jURLencode($filename); //jusi: changed, original above
    			}
    		} else {
    			if ($this->_config['canDownload']) {
    				if ($this->_config['usePlugin']) {
    					if ($this->_config['multiFolders']) {
    						$multiFolderLink = '&dir=' . $multiFolderNum;
    					} else {
    						$multiFolderLink = '';
    					}
    					if(strlen($this->_config['curRelPath'])) {
    						//$filelocat = $this->_config['curRelPath'] . '/' . $filename;
    						$filelocat = $this->_config['curRelPath'] . '/' . jURLencode($filename); //jusi: changed, original above
    					} else {
    						//$filelocat = $filename;
    						$filelocat = jURLencode($filename); //jusi: changed, original above
    					}
    					//if ($this->_config['urlsetting'] == '?') {
    					//	$fileLink = $this->_config['curUrl'].'/'.$filelocat . $multiFolderLink;
    					//} else {
    						$fileLink = $this->_config['curUrl'].'&d='.$filelocat . $multiFolderLink;
    					//}
    					// jusi: above are three lines commented out for filedownload to work with default friendly url rewrite rule of modx
    				} else {
    					$fileLink = $filelocat;
    				}
    			} else {
    				$fileLink = 'javascript:alert(\''.$this->_lang['noDownload'].'\')';
    			}
    		}
    		return $fileLink;
    	}
    
    	function getFiles($path,$multiFolderNum=0) {
    		$files = array();
    
    		if (is_dir($path)) {
    			if ($dh = opendir($path)) {
    				$i = 0;
    				$countFiles = 0;
    				$countDirs = 0;
    
    				while (($file = readdir($dh)) !== false) {
    					if ($file == '.' || $file == '..' || $file == '.htaccess' || $file == '.htpasswd') continue;
    
    					if ($this->_config['getFile']) {
    						if ($file !== $this->_config['getFile']) {
    							continue;
    						}
    					}
    
    					$fullpath = $path . '/' . $file;
    
    					//Check extension if valid extensions are specified & remove folders if no Browse Directory
    					$extension = strtolower(substr($file,strrpos($file,'.')+1));
    					$fileType = filetype($fullpath);
    					$isDir = ($fileType == 'dir') ? 1 : 0 ;
    
    					if ($this->_config['browseDirectories']) {
    						if ($isDir) {
    							$validFile = 1;
    						} else {
    							$validFile = $this->_config['filterExt'] ? $this->validExtension($extension) : 1 ;
    						}
    					} else {
    						if ($isDir) {
    							$validFile = 0;
    						} else {
    							$validFile = $this->_config['filterExt'] ? $this->validExtension($extension) : 1 ;
    						}
    					}
    
    					if ($validFile) {
    						$fileStats = stat($fullpath);
    						//$files[$i]['filename'] = $file;
    						$files[$i]['filename'] = htmlentities($file); //jusi: changed, original above
    						$files[$i]['extension'] = $isDir ? '' : $extension;
    						$files[$i]['path'] = $path;
    						$files[$i]['size'] = $isDir ? '' : $fileStats['size'];
    						$files[$i]['sizetext'] = $isDir ? '-' : $this->fileSizeText($fileStats['size']);
    						$files[$i]['type'] = $fileType;
    						$files[$i]['date'] = date($this->_config['dateFormat'],$fileStats['mtime']);
    						$files[$i]['description'] = $this->_config['chkDesc'] ? $this->getDescription($fullpath) : '';
    						if ($this->_config['imgTypes']) {
    							$files[$i]['image'] = $isDir ? $this->selectImage('folder') : $this->selectImage($extension);
    						} else {
    							$files[$i]['image'] = '';
    						}
    						$files[$i]['delete'] = md5('act:del||filename:'.$fullpath);
    						$files[$i]['count'] = $isDir ? '' : $this->_config['countDownloads'] ? $this->getDownloadCount($fullpath) : 0;
    						$files[$i]['link'] = $this->createLink($isDir,$fullpath,$file,0,$fileStats['size'],$multiFolderNum);
    						if ($fileType == 'dir') {
    							$countDirs++;
    						} else {
    							$countFiles++;
    						}
    					}
    					if ($this->_config['getFile']) {
    						if ($file == $this->_config['getFile']) {
    							break;
    						}
    					}
    					$i++;
    				}
    				closedir($dh);
    			} else $files = $this->_lang['dirOpenError'].$path;
    		} else $files = $this->_lang['notaDir'].$path;
    		$this->fcounts[$path]['dirs'] = $countDirs;
    		$this->fcounts[$path]['files'] = $countFiles;
    		return $files;
    	}
    
    	function getDefaultLayout() {
    		$t='<table>';
    		if ($this->_config['browseDirectories']) {
    			$t .= '<tr[+fd.class+]><td colspan="4"><strong>Path: [+fd.path+]</strong></td></tr>';
    		}
    		$t .= '<tr><th colspan="2">Filename</th><th>Filesize</th><th>Date</th></tr>
    			'.$this->_config['splitter'].'
    				<tr[+fd.class+]>
    					<td>'.($this->_config['imgTypes']?'<img src="[+fd.image+]"/>':'').'</td>
    					<td colspan="3"><a href="[+fd.link+]">Up Level</a></td>
    				</tr>
    			'.$this->_config['splitter'].'
    				<tr[+fd.class+]>
    					<td>'.($this->_config['imgTypes']?'<img src="[+fd.image+]"/>':'').'</td>
    					<td colspan="3"><a href="[+fd.link+]">[+fd.filename+]</a></td>
    				</tr>
    			'.$this->_config['splitter'].'
    				<tr[+fd.class+]>
    					<td>'.($this->_config['imgTypes']?'<img src="[+fd.image+]"/>':'').'</td>
    					<td><a href="[+fd.link+]">[+fd.filename+]</a>'.($this->_config['countDownloads']?' <span style="font-size:80%">([+fd.count+] downloads) [+fd.delete+]</span>':' [+fd.delete+]').'</td>
    					<td>[+fd.sizetext+]</td>
    					<td>[+fd.date+]</td>
    				</tr>
    				<tr><td></td><td colspan="3">[+fd.description+]</td></tr>
    			'.$this->_config['splitter'].'
    				<a href="[+fd.deletelink+]">Delete</a>
    			'.$this->_config['splitter'].'
    				<tr[+fd.class+]>
    					<td colspan="4"><strong>[+fd.directory+]</strong></td>
    				</tr>
    			'.$this->_config['splitter'].'
    			</table>';
    
    		return $t;
    	}
    
    	function getTemplateArray($html,$tplSeparator) {
    		list($tpl['header'],$tpl['parent'],$tpl['folder'],$tpl['row'],$tpl['delete'],$tpl['directory'],$tpl['footer']) = explode($tplSeparator,$html);
    		return $tpl;
    	}
    
    	function customSort(&$finalArray, $fields, $order) {
    		// Covert $fields string to array
    		foreach (explode(',', $fields) as $s)
    			$sortfields[] = trim($s);
    
    		$code = "";
    
    		for ($c = 0; $c < count($sortfields); $c++) {
    			$code .= "\$retval = strnatcmp(strtolower(\$a['$sortfields[$c]']), strtolower(\$b['$sortfields[$c]'])); if(\$retval) return \$retval; ";
    		}
    
    		$code .= "return \$retval;";
    
    		$params = ($order == 'asc') ? '$a,$b' : '$b,$a';
    		usort($finalArray, create_function($params, $code));
    	}
    
    	function loadCounts() {
    		global $modx;
    		$loadWhere = ($this->_config['useDbCount']) ? 'db' : 'file';
    		$this->_config['downloadCount'] = $this->db->loadCounts($this->db->config['fdTable'],$loadWhere,$this->_config['fileCount']);
    	}
    
    	function setClass($type,$alt=0,$first=0,$last=0,$ext='') {
    		$class = '';
    
    		switch ($type) {
    			case 'dir':
    				if ($this->_config['css']['folder']) $class .= $this->_config['css']['folder'] . ' ';
    				if ($this->_config['css']['alt'] && $alt) $class .= $this->_config['css']['alt'] . ' ';
    				if ($this->_config['css']['firstFolder'] && $first) $class .= $this->_config['css']['firstFolder'] . ' ';
    				if ($this->_config['css']['lastFolder'] && $last) $class .= $this->_config['css']['lastFolder'] . ' ';
    				break;
    			case 'file':
    				if ($this->_config['css']['file']) $class .= $this->_config['css']['file'] . ' ';
    				if ($this->_config['css']['alt'] && $alt) $class .= $this->_config['css']['alt'] . ' ';
    				if ($this->_config['css']['firstFile'] && $first) $class .= $this->_config['css']['firstFile'] . ' ';
    				if ($this->_config['css']['lastFile'] && $last) $class .= $this->_config['css']['lastFile'] . ' ';
    				if ($this->_config['css']['extension']) $class .= 'fd-' . $ext . ' ';
    				break;
    			case 'path':
    				if ($this->_config['css']['path']) $class .= $this->_config['css']['path'] . ' ';
    				if ($this->_config['css']['alt'] && $alt) $class .= $this->_config['css']['alt'] . ' ';
    				break;
    			case 'multidir':
    				if ($this->_config['css']['directory']) $class .= $this->_config['css']['directory'] . ' ';
    				if ($this->_config['css']['alt'] && $alt) $class .= $this->_config['css']['alt'] . ' ';
    				break;
    			case 'parent':
    				if ($this->_config['css']['parent']) $class .= $this->_config['css']['parent'] . ' ';
    				if ($this->_config['css']['alt'] && $alt) $class .= $this->_config['css']['alt'] . ' ';
    				break;
    		}
    
    		$class = $class ? ' class="'.trim($class).'"' : '';
    
    		return $class;
    	}
    
    	function deleteFile() {
    		foreach ($this->allFiles as $n=>$v) {
    			$delParam = $_GET['act'];
    			if ($delParam == $v['delete']) {
    				$dfilename = $v['path'] . '/' . $v['filename'];
    				$delReturn = @ unlink($dfilename);
    				if ($delReturn) {
    					unset($this->allFiles[$n]);
    					return '<span class="fd-delete-msg">'.$this->_lang['delSuccess'].$v['filename'].'</span>';
    				} else {
    					return '<span class="fd-delete-msg">'.$this->_lang['delError'].$v['filename'].'</span>';
    				}
    			}
    		}
    		return '<span class="fd-delete-msg">You can\'t delete that file!</span>';
    	}
    }
    ?>
    


    ... and of course NO guaratees for this to work at your install and for not breaking security holes in the script...

    Greetz
    JUSI
      • 30087
      • 23 Posts
      Does anyone know if there is an easy solution to add pagination?
        • 22282
        • 10 Posts
        Hello,

        Great snippet.
        Is it possible to have it list multiple files from the one directory in a single call of snippet?

        EG:

        I have a list of files in one directory. I want different users to see different files within that directory. So I was considering creating a new document for each user group with a snippet call for their files. I can only seem to list the entire directory (excluding filtering) or one file per call.

        I need this to be secure that is why I am using fileDownload and the plugin. I cannot make different directories for each user as some of the files are several gigabytes, duplication is not an option. Please let me know if it is possible or if there is a better solution to my problem.

        Thanks.
          • 29131
          • 11 Posts
          Hi

          Is it possible to add - when I calling snippet [!FileDownload? ... !] - limit of number of files which will be displayed by the snippet.

          For example:
          I have got 10 files in a directory, but I want to show any 3 newest.

          THX for help
            • 15082
            • 195 Posts
            Hi Szakul,

            haven’t tried it myself but maybe (as a quick and dirty solution) you can tweak the output by using a template, that contains an empty files section and renders the output solely from the folder section, where you only specify your desired amount of table rows...

            Please refer to http://www.muddydogpaws.com/development/filedownload/parameters.html (section "Template & Style")

            Greetz
            JUSI
              • 29131
              • 11 Posts
              Quote from: jusicgn at Jun 30, 2010, 11:00 AM

              Hi Szakul,

              haven’t tried it myself but maybe (as a quick and dirty solution) you can tweak the output by using a template, that contains an empty files section and renders the output solely from the folder section, where you only specify your desired amount of table rows...

              Please refer to http://www.muddydogpaws.com/development/filedownload/parameters.html (section "Template & Style")

              Greetz
              JUSI

              Thank You for quick answer.
              I tried but it doesn’t work. It still show me all files.

                • 29131
                • 11 Posts
                jusicgn -> Really thx for help

                I found another solution. And it works. I know it isn’t perfect, but I haven’t got another idea


                HOW TO ADD LIMIT of results in FileDownload

                1. Add $fileDownload->Set(’limit’,$limit); line to the FileDownload snippet.
                2. Add $this->_config[’limit’] = !is_null($this->Get(’limit’)) ? $this->Get(’limit’) : 999999999999999;
                to the file filedownload.class.inc.php to the function Run.

                3. Add $limit++; below this line foreach ($this->allFiles as $n=>$v) {
                = more/less line no. 226

                4. Add if ( $limit== $this->_config[’limit’]) break; before } (the end of foreach)

                5. Call [!FileDownload? ........... &limit=`your number` !].


                  • 26871
                  • 2 Posts
                  Hey,
                  can somebody help me?
                  I want to open the files in a new window instead of the same. This is especially for pdf files i’m offering on my site.

                  thanks a lot for ur help
                  cheers
                    • 14214
                    • 299 Posts
                    Within your FileDownload template you need to specify the target (i.e. target="_blank") for each line.

                    This is what I am using:
                    <table>
                    	<tr[+fd.class+]></tr>
                    	<tr><th colspan="2" width="400px" align="left"><h5>Filename</h5></th><th><h5>File Size</h5></th></tr>
                    <!-- Fd:Splitter -->
                    	<tr[+fd.class+]>
                    		<td><a href="[+fd.link+]"><img src="[+fd.image+]" style="float:left; padding-top:5px; padding-bottom:15px; border:0;" /></a></td>
                    		<td colspan="3"><h4><a href="[+fd.link+]">< Return to Previous Folder</a></h4></td>
                    	</tr>
                    <!-- Fd:Splitter -->
                    	<tr[+fd.class+]>
                    		<td><a href="[+fd.link+]"><img src="[+fd.image+]" style="padding-bottom:8px;  border:0;" /></a></td>
                    		<td ><h5><a href="[+fd.link+]" style="color:#0079C1; size:13px; margin-left:0px;" >[+fd.filename+]</a><h5></td>
                    	</tr>
                    <!-- Fd:Splitter -->
                    	<tr[+fd.class+]>
                    		<td><a href="[+fd.link+]" target="_blank"><img src="[+fd.image+]" border="0"/></a></td>
                    		<td><a href="[+fd.link+]" target="_blank">[+filenumber+][+fd.filename+] </a> </td>
                    		<td>[+fd.sizetext+]</td>
                    
                    	</tr>
                    	<tr><td></td><td colspan="3">[+fd.description+]</td></tr>
                    <!-- Fd:Splitter -->
                    	<a href="[+fd.deletelink+]">Delete</a>
                    <!-- Fd:Splitter -->
                    	<tr[+fd.class+]>
                    		<td colspan="4"><strong>[+fd.directory+]</strong></td>
                    	</tr>
                    <!-- Fd:Splitter -->
                    </table>

                    Hope this helps...
                      • 10154
                      • 8 Posts
                      Hello,

                      I’m just wondering if there is a possibility to exclude thumbnails from the result list. I want to keep the normal sized jpg-images. Any idea?