public static function download($fileData, $downloadId, $currentLink, $type = 0) { $app = JFactory::getApplication(); $params = $app->getParams(); $directLink = $fileData['directlink']; // Direct Link 0 or 1 $externalLink = $fileData['externallink']; $absOrRelFile = $fileData['file']; // Relative Path or Absolute Path // Type = 1 - Token - unique download link - cannot be direct if ($type == 1) { $directLink = 0; } // NO FILES FOUND (abs file) $error = false; $error = preg_match("/COM_PHOCADOWNLOAD_ERROR/i", $absOrRelFile); if ($error) { $msg = JText::_('COM_PHOCADOWNLOAD_ERROR_WHILE_DOWNLOADING_FILE') . ' ' . JText::_($absOrRelFile); $app->redirect(JRoute::_($currentLink), $msg); } else { // Get extensions $extension = JFile::getExt(strtolower($absOrRelFile)); $aft = $params->get('allowed_file_types_download', PhocaDownloadSettings::getDefaultAllowedMimeTypesDownload()); $dft = $params->get('disallowed_file_types_download', ''); // Get Mime from params ( ext --> mime) $allowedMimeType = PhocaDownloadFile::getMimeType($extension, $aft); $disallowedMimeType = PhocaDownloadFile::getMimeType($extension, $dft); // NO MIME FOUND $errorAllowed = false; // !!! IF YES - Disallow Downloading $errorDisallowed = false; // !!! IF YES - Allow Downloading $errorAllowed = preg_match("/PhocaError/i", $allowedMimeType); $errorDisallowed = preg_match("/PhocaError/i", $disallowedMimeType); $ignoreDownloadCheck = $params->get('ignore_file_types_check', 2); if ($ignoreDownloadCheck == 3 || $ignoreDownloadCheck == 4 || $ignoreDownloadCheck == 5) { $errorAllowed = false; $errorDisallowed = true; } if ($errorAllowed) { $msg = JText::_('COM_PHOCADOWNLOAD_WARNFILETYPE_DOWNLOAD'); $app->redirect(JRoute::_($currentLink), $msg); } else { if (!$errorDisallowed) { $msg = JText::_('COM_PHOCADOWNLOAD_WARNFILETYPE_DISALLOWED_DOWNLOAD'); $app->redirect(JRoute::_($currentLink), $msg); } else { if ($directLink == 1) { // Direct Link on the same server $fileWithoutPath = basename($absOrRelFile); $addHit = self::hit($downloadId); if ($type == 1) { self::hitToken($downloadId); } if ((int) $params->get('send_mail_download', 0) > 0) { PhocaDownloadMail::sendMail((int) $params->get('send_mail_download', 0), $fileWithoutPath, 1); } // USER Statistics if ((int) $params->get('enable_user_statistics', 1) == 1) { $addUserStat = PhocaDownloadStat::createUserStatEntry($downloadId); } PhocaDownloadLog::log($downloadId, 1); $app->redirect($absOrRelFile); exit; } else { if ($directLink == 0 && $externalLink != '') { // External Link but with redirect // In case there is directLink the external Link does not go this way but directly to the external URL $addHit = self::hit($downloadId); if ($type == 1) { self::hitToken($downloadId); } if ((int) $params->get('send_mail_download', 0) > 0) { PhocaDownloadMail::sendMail((int) $params->get('send_mail_download', 0), $externalLink, 1); } // USER Statistics if ((int) $params->get('enable_user_statistics', 1) == 1) { $addUserStat = PhocaDownloadStat::createUserStatEntry($downloadId); } PhocaDownloadLog::log($downloadId, 1); $app->redirect($externalLink); exit; } else { // Clears file status cache clearstatcache(); $fileWithoutPath = basename($absOrRelFile); $fileSize = filesize($absOrRelFile); $mimeType = ''; $mimeType = $allowedMimeType; // HIT Statistics $addHit = self::hit($downloadId); if ($type == 1) { self::hitToken($downloadId); } if ((int) $params->get('send_mail_download', 0) > 0) { PhocaDownloadMail::sendMail((int) $params->get('send_mail_download', 0), $fileWithoutPath, 1); } // USER Statistics if ((int) $params->get('enable_user_statistics', 1) == 1) { $addUserStat = PhocaDownloadStat::createUserStatEntry($downloadId); } PhocaDownloadLog::log($downloadId, 1); if ($fileSize == 0) { die(JText::_('COM_PHOCADOWNLOAD_FILE_SIZE_EMPTY')); exit; } // Clean the output buffer ob_end_clean(); // test for protocol and set the appropriate headers jimport('joomla.environment.uri'); $_tmp_uri = JURI::getInstance(JURI::current()); $_tmp_protocol = $_tmp_uri->getScheme(); if ($_tmp_protocol == "https") { // SSL Support header('Cache-Control: private, max-age=0, must-revalidate, no-store'); } else { header("Cache-Control: public, must-revalidate"); header('Cache-Control: pre-check=0, post-check=0, max-age=0'); header("Pragma: no-cache"); header("Expires: 0"); } /* end if protocol https */ header("Content-Description: File Transfer"); header("Expires: Sat, 30 Dec 1990 07:07:07 GMT"); header("Accept-Ranges: bytes"); // HTTP Range /* $httpRange = 0; if(isset($_SERVER['HTTP_RANGE'])) { list($a, $httpRange) = explode('=', $_SERVER['HTTP_RANGE']); str_replace($httpRange, '-', $httpRange); $newFileSize = $fileSize - 1; $newFileSizeHR = $fileSize - $httpRange; header("HTTP/1.1 206 Partial Content"); header("Content-Length: ".(string)$newFileSizeHR); header("Content-Range: bytes ".$httpRange . $newFileSize .'/'. $fileSize); } else { $newFileSize = $fileSize - 1; header("Content-Length: ".(string)$fileSize); header("Content-Range: bytes 0-".$newFileSize . '/'.$fileSize); } header("Content-Type: " . (string)$mimeType); header('Content-Disposition: attachment; filename="'.$fileWithoutPath.'"'); header("Content-Transfer-Encoding: binary\n");*/ // Modified by Rene // HTTP Range - see RFC2616 for more informations (http://www.ietf.org/rfc/rfc2616.txt) $httpRange = 0; $newFileSize = $fileSize - 1; // Default values! Will be overridden if a valid range header field was detected! $resultLenght = (string) $fileSize; $resultRange = "0-" . $newFileSize; // We support requests for a single range only. // So we check if we have a range field. If yes ensure that it is a valid one. // If it is not valid we ignore it and sending the whole file. if (isset($_SERVER['HTTP_RANGE']) && preg_match('%^bytes=\\d*\\-\\d*$%', $_SERVER['HTTP_RANGE'])) { // Let's take the right side list($a, $httpRange) = explode('=', $_SERVER['HTTP_RANGE']); // and get the two values (as strings!) $httpRange = explode('-', $httpRange); // Check if we have values! If not we have nothing to do! if (!empty($httpRange[0]) || !empty($httpRange[1])) { // We need the new content length ... $resultLenght = $fileSize - $httpRange[0] - $httpRange[1]; // ... and we can add the 206 Status. header("HTTP/1.1 206 Partial Content"); // Now we need the content-range, so we have to build it depending on the given range! // ex.: -500 -> the last 500 bytes if (empty($httpRange[0])) { $resultRange = $resultLenght . '-' . $newFileSize; } elseif (empty($httpRange[1])) { $resultRange = $httpRange[0] . '-' . $newFileSize; } else { $resultRange = $httpRange[0] . '-' . $httpRange[1]; } //header("Content-Range: bytes ".$httpRange . $newFileSize .'/'. $fileSize); } } header("Content-Length: " . $resultLenght); header("Content-Range: bytes " . $resultRange . '/' . $fileSize); header("Content-Type: " . (string) $mimeType); header('Content-Disposition: attachment; filename="' . $fileWithoutPath . '"'); header("Content-Transfer-Encoding: binary\n"); // TEST TEMP SOLUTION ob_end_clean(); //@readfile($absOrRelFile); // Try to deliver in chunks @set_time_limit(0); $fp = @fopen($absOrRelFile, 'rb'); if ($fp !== false) { while (!feof($fp)) { echo fread($fp, 8192); } fclose($fp); } else { @readfile($absOrRelFile); } flush(); exit; /* http://www.phoca.cz/forum/viewtopic.php?f=31&t=11811 $fp = @fopen($absOrRelFile, 'rb'); // HTTP Range - see RFC2616 for more informations (http://www.ietf.org/rfc/rfc2616.txt) $newFileSize = $fileSize - 1; // Default values! Will be overridden if a valid range header field was detected! $rangeStart = 0; $rangeEnd = 0; $resultLength = $fileSize; // We support requests for a single range only. // So we check if we have a range field. If yes ensure that it is a valid one. // If it is not valid we ignore it and sending the whole file. if ($fp && isset($_SERVER['HTTP_RANGE']) && preg_match('%^bytes=\d*\-\d*$%', $_SERVER['HTTP_RANGE'])) { // Let's take the right side list($a, $httpRange) = explode('=', $_SERVER['HTTP_RANGE']); // and get the two values (as strings!) $httpRange = explode('-', $httpRange); // Check if we have values! If not we have nothing to do! if (sizeof($httpRange) == 2) { // Explictly convert to int $rangeStart = intval($httpRange[0]); $rangeEnd = intval($httpRange[1]); // Allowed to be empty == 0 if (($rangeStart || $rangeEnd) // something actually set? && $rangeStart < $fileSize // must be smaller && $rangeEnd < $fileSize // must be smaller && (!$rangeEnd || $rangeEnd > $rangeStart) // end > start, if end is set ) { header("HTTP/1.1 206 Partial Content"); if (!$rangeEnd) { $resultLength = $fileSize - $rangeStart; $range = $rangeStart . "-" . ($fileSize - 1) . "/" . $fileSize; } else { $resultLength = ($rangeEnd - $rangeStart 1); $range = $rangeStart . "-" . $rangeEnd . "/" . $fileSize; } header("Content-Range: bytes " . $range); } else { // Didn't validate: kill $rangeStart = 0; $rangeEnd = 0; } } } header("Content-Length: ". $resultLength); header("Content-Type: " . (string)$mimeType); header('Content-Disposition: attachment; filename="'.$fileWithoutPath.'"'); header("Content-Transfer-Encoding: binary\n"); @@ -211,13 +198,25 @@ class PhocaDownloadAccessFront // Try to deliver in chunks @set_time_limit(0); if ($fp !== false) { if ($rangeStart) { // Need to pass only part of the file, starting at $rangeStart fseek($fp, $rangeStart, SEEK_SET); } // If $rangeEnd is open ended (0, whole file from $rangeStart) try fpassthru, // else send in small chunks if ($rangeEnd || @!fpassthru($fp)) { while ($resultLength > 0 && !feof($fp)) { // 4 * 1460 (default MSS with ethernet 1500 MTU) // This is optimized for network packets, not disk access $bytes = min(5840, $resultLength); echo fread($fp, $bytes); $resultLength = $resultLength - $bytes; } } fclose($fp); } else { // Ranges are disabled at this point and were never set up @readfile($absOrRelFile); } flush(); exit; */ } } } } } return false; }
function display($tpl = null) { $app = JFactory::getApplication(); $document = JFactory::getDocument(); $uri = JFactory::getURI(); $menus = $app->getMenu(); $menu = $menus->getActive(); $this->t['p'] = $app->getParams(); $user = JFactory::getUser(); $db = JFactory::getDBO(); $user = JFactory::getUser(); $userLevels = implode(',', $user->getAuthorisedViewLevels()); $this->t['pi'] = 'media/com_phocadownload/images/'; $this->t['pp'] = 'index.php?option=com_phocadownload&view=user&controller=user'; $this->t['pl'] = 'index.php?option=com_users&view=login&return=' . base64_encode($this->t['pp'] . '&Itemid=' . $app->input->get('Itemid', 0, 'int')); $neededAccessLevels = PhocaDownloadAccess::getNeededAccessLevels(); $access = PhocaDownloadAccess::isAccess($user->getAuthorisedViewLevels(), $neededAccessLevels); if (!$access) { $app->redirect(JRoute::_($this->t['pl'], false), JText::_("COM_PHOCADOWNLOAD_NOT_AUTHORISED_ACTION")); return; } PhocaDownloadRenderFront::renderAllCSS(); // = = = = = = = = = = = // PANE // = = = = = = = = = = = // - - - - - - - - - - // ALL TABS // - - - - - - - - - - // UCP is disabled (security reasons) if ((int) $this->t['p']->get('enable_user_cp', 0) == 0) { $app->redirect(JURI::base(false), JText::_("COM_PHOCADOWNLOAD_USER_UPLOAD_DISABLED")); exit; } $this->t['tab'] = $app->input->get('tab', 0, 'string'); $this->t['maxuploadchar'] = $this->t['p']->get('max_upload_char', 1000); $this->t['enableuseruploadapprove'] = $this->t['p']->get('enable_user_upload_approve', 0); $this->t['showpageheading'] = $this->t['p']->get('show_page_heading', 1); $this->t['uploadmaxsize'] = $this->t['p']->get('user_file_upload_size', 3145728); $this->t['uploadmaxsizeread'] = PhocaDownloadFile::getFileSizeReadable($this->t['uploadmaxsize']); $this->t['userfilesmaxcount'] = $this->t['p']->get('user_files_max_count', 5); $this->t['userfilesmaxsize'] = $this->t['p']->get('user_files_max_size', 20971520); $this->t['send_mail_upload'] = $this->t['p']->get('send_mail_upload', 0); $this->t['pw'] = PhocaDownloadRenderFront::renderPhocaDownload(); //Subcateogry //$this->t['parentid'] = $app->input->get('parentcategoryid', 0, 'int'); //$document->addScript(JURI::base(true).'/components/com_phocadownload/assets/js/comments.js'); $document->addCustomTag(PhocaDownloadRenderFront::renderOnUploadJS()); $document->addCustomTag(PhocaDownloadRenderFront::renderDescriptionUploadJS((int) $this->t['maxuploadchar'])); $document->addCustomTag(PhocaDownloadRenderFront::userTabOrdering()); $model = $this->getModel('user'); // Upload Form - - - - - - - - - - - - - - - $ftp = !JClientHelper::hasCredentials('ftp'); // Set FTP form $session = JFactory::getSession(); $this->assignRef('session', $session); // END Upload Form - - - - - - - - - - - - - $this->t['displayupload'] = 1; // - - - - - - - - - - // FORM // - - - - - - - - - - // No Controller because of returning back the values in case some form field is not OK // Set default for returning back $formData = new JObject(); $formData->set('title', ''); $formData->set('description', ''); $formData->set('author', ''); $formData->set('email', ''); $formData->set('license', ''); $formData->set('website', ''); $formData->set('version', ''); $this->t['errorcatid'] = ''; $this->t['erroremail'] = ''; $this->t['errorwebsite'] = ''; $this->t['errorfile'] = ''; $task = $app->input->get('task', '', 'string'); if ($task == 'upload') { $post['title'] = $app->input->get('phocadownloaduploadtitle', '', 'string'); $post['description'] = $app->input->get('phocadownloaduploaddescription', '', 'string'); $post['catidfiles'] = $app->input->get('catidfiles', 0, 'int'); $post['description'] = substr($post['description'], 0, (int) $this->t['maxuploadchar']); $post['approved'] = 0; $post['published'] = 1; $post['owner_id'] = $user->id; if ($this->t['enableuseruploadapprove'] == 0) { $post['approved'] = 1; } $post['author'] = $app->input->get('phocadownloaduploadauthor', '', 'string'); $post['email'] = $app->input->get('phocadownloaduploademail', '', 'string'); $post['website'] = $app->input->get('phocadownloaduploadwebsite', '', 'string'); $post['license'] = $app->input->get('phocadownloaduploadlicense', '', 'string'); $post['version'] = $app->input->get('phocadownloaduploadversion', '', 'string'); if ($post['title'] != '') { $formData->set('title', $post['title']); } if ($post['description'] != '') { $formData->set('description', $post['description']); } if ($post['author'] != '') { $formData->set('author', $post['author']); } if ($post['email'] != '') { $formData->set('email', $post['email']); } if ($post['website'] != '') { $formData->set('website', $post['website']); } if ($post['license'] != '') { $formData->set('license', $post['license']); } if ($post['version'] != '') { $formData->set('version', $post['version']); } //catid $returnForm = 0; if ($post['catidfiles'] < 1) { $this->t['errorcatid'] = JText::_('COM_PHOCADOWNLOAD_PLEASE_SELECT_CATEGORY'); $returnForm = 1; } jimport('joomla.mail.helper'); if ($post['email'] != '' && !JMailHelper::isEmailAddress($post['email'])) { $this->t['erroremail'] = JText::_('COM_PHOCADOWNLOAD_PLEASE_ENTER_VALID_EMAIL_ADDRESS'); $returnForm = 1; } if ($post['website'] != '' && !PhocaDownloadUtils::isURLAddress($post['website'])) { $this->t['errorwebsite'] = JText::_('COM_PHOCADOWNLOAD_PLEASE_ENTER_VALID_WEBSITE'); $returnForm = 1; } // Upload $errUploadMsg = ''; $redirectUrl = ''; $fileArray = JRequest::getVar('Filedata', '', 'files', 'array'); if (empty($fileArray) || isset($fileArray['name']) && $fileArray['name'] == '') { $this->t['errorfile'] = JText::_('COM_PHOCADOWNLOAD_PLEASE_ADD_FILE'); $returnForm = 1; } if ($post['title'] == '') { $post['title'] = PhocaDownloadFile::removeExtension($fileArray['name']); } $post['alias'] = PhocaDownloadUtils::getAliasName($post['title']); if ($returnForm == 0) { $errorUploadMsg = ''; if ($model->singleFileUpload($errorUploadMsg, $fileArray, $post)) { if ($this->t['send_mail_upload'] > 0) { PhocaDownloadMail::sendMail((int) $this->t['send_mail_upload'], $post['title'], 2); } $Itemid = $app->input->get('Itemid', 0, 'int'); $limitStart = $app->input->get('limitstart', 0, 'int'); if ($limitStart > 0) { $limitStartUrl = '&limitstart=' . $limitStart; } else { $limitStartUrl = ''; } $link = 'index.php?option=com_phocadownload&view=user&Itemid=' . $Itemid . $limitStartUrl; $app->redirect(JRoute::_($link, false), JText::_("COM_PHOCADOWNLOAD_SUCCESS_FILE_UPLOADED")); exit; } else { $this->t['errorfile'] = JText::_('COM_PHOCADOWNLOAD_ERROR_FILE_UPLOADED'); if ($errorUploadMsg != '') { $this->t['errorfile'] .= '<br />' . $errorUploadMsg; } } } } // - - - - - - - - - - - // FILES // - - - - - - - - - - - $this->t['filesitems'] = $model->getDataFiles($user->id); $this->t['filestotal'] = $model->getTotalFiles($user->id); $this->t['filespagination'] = $model->getPaginationFiles($user->id); $filter_state_files = $app->getUserStateFromRequest($this->_context_files . '.filter_state', 'filter_state', '', 'word'); $filter_catid_files = $app->getUserStateFromRequest($this->_context_files . '.filter_catid', 'filter_catid', 0, 'int'); $catid_files = $app->getUserStateFromRequest($this->_context_files . '.catid', 'catid', 0, 'int'); //$filter_sectionid_files = $app->getUserStateFromRequest( $this->_context_files.'.filter_sectionid', 'filter_sectionid', 0, 'int' ); $filter_order_files = $app->getUserStateFromRequest($this->_context_files . '.filter_order', 'filter_order', 'a.ordering', 'cmd'); $filter_order_Dir_files = $app->getUserStateFromRequest($this->_context_files . '.filter_order_Dir', 'filter_order_Dir', '', 'word'); $search_files = $app->getUserStateFromRequest($this->_context_files . '.search', 'search', '', 'string'); $search_files = JString::strtolower($search_files); // build list of categories $javascript = 'class="inputbox" size="1" onchange="document.phocadownloadfilesform.submit();"'; // get list of categories for dropdown filter $whereC = array(); //if ($filter_sectionid_files > 0) { // $whereC[] = ' cc.section = '.$db->Quote($filter_sectionid_files); //} //$whereC[] = "(cc.uploaduserid LIKE '%-1%' OR cc.uploaduserid LIKE '%".(int)$user->id."%')"; //$whereC[] = "(cc.uploaduserid LIKE '%-1%' OR cc.uploaduserid LIKE '%,{".(int)$user->id."}' OR cc.uploaduserid LIKE '{".(int)$user->id."},%' OR cc.uploaduserid LIKE '%,{".(int)$user->id."},%' OR cc.uploaduserid ={".(int)$user->id."} )"; $whereC[] = "(cc.uploaduserid LIKE '%-1%' OR cc.uploaduserid LIKE '%," . (int) $user->id . "' OR cc.uploaduserid LIKE '" . (int) $user->id . ",%' OR cc.uploaduserid LIKE '%," . (int) $user->id . ",%' OR cc.uploaduserid =" . (int) $user->id . " )"; $whereC = count($whereC) ? ' WHERE ' . implode(' AND ', $whereC) : ''; // get list of categories for dropdown filter $query = 'SELECT cc.id AS value, cc.title AS text, cc.parent_id as parentid' . ' FROM #__phocadownload_categories AS cc' . $whereC . ' ORDER BY cc.ordering'; $lists_files['catid'] = PhocaDownloadCategory::filterCategory($query, $catid_files, TRUE, TRUE, TRUE); /*$whereS = array(); //$whereS[] = "(cc.uploaduserid LIKE '%-1%' OR cc.uploaduserid LIKE '%".(int)$user->id."%')"; $whereS[] = "(cc.uploaduserid LIKE '%-1%' OR cc.uploaduserid LIKE '%,".(int)$user->id."' OR cc.uploaduserid LIKE '".(int)$user->id.",%' OR cc.uploaduserid LIKE '%,".(int)$user->id.",%' OR cc.uploaduserid =".(int)$user->id." )"; $whereS[] = 's.published = 1'; $whereS = ( count( $whereS ) ? ' WHERE '. implode( ' AND ', $whereS ) : '' ); // sectionid $query = 'SELECT s.title AS text, s.id AS value' . ' FROM #__phocadownload_sections AS s' . ' LEFT JOIN #__phocadownload_categories AS cc ON cc.section = s.id' . $whereS . ' GROUP BY s.id' . ' ORDER BY s.ordering'; // state filter /* $state_files[] = JHTML::_('select.option', '', '- '. JText::_( 'Select State' ) .' -' ); $state_files[] = JHTML::_('select.option', 'P', JText::_( 'Published' ) ); $state_files[] = JHTML::_('select.option', 'U', JText::_( 'Unpublished') ); $lists_image['state'] = JHTML::_('select.genericlist', $state_files, 'filter_state', 'class="inputbox" size="1" onchange="document.phocadownloadfilesform.submit();"', 'value', 'text', $filter_state );*/ //$lists_files['sectionid'] = PhocaDownloadCategory::filterSection($query, $filter_sectionid_files, TRUE); // state filter $lists_files['state'] = JHTML::_('grid.state', $filter_state_files); // table ordering $lists_files['order_Dir'] = $filter_order_Dir_files; $lists_files['order'] = $filter_order_files; // search filter $lists_files['search'] = $search_files; $this->t['catidfiles'] = $catid_files; $this->t['filestab'] = 1; // Tabs $displayTabs = 0; if ((int) $this->t['filestab'] == 0) { $currentTab['files'] = -1; } else { $currentTab['files'] = $displayTabs; $displayTabs++; } $this->t['displaytabs'] = $displayTabs; $this->t['currenttab'] = $currentTab; // ACTION $this->t['action'] = $uri->toString(); // SEF problem $isThereQM = false; $isThereQM = preg_match("/\\?/i", $this->t['action']); if ($isThereQM) { $amp = '&'; } else { $amp = '?'; } $this->t['actionamp'] = htmlspecialchars($this->t['action']) . $amp; $this->t['istheretab'] = false; $this->t['istheretab'] = preg_match("/tab=/i", $this->t['action']); $this->t['ps'] = '&tab=' . $this->t['currenttab']['files'] . '&limitstart=' . $this->t['filespagination']->limitstart; // ASIGN $this->assignRef('listsfiles', $lists_files); $this->assignRef('formdata', $formData); $this->assignRef('tmpl', $this->t); $this->assignRef('params', $this->t['p']); $session = JFactory::getSession(); $this->assignRef('session', $session); parent::display($tpl); }