HomeHelpTrac

Changeset 15476


Ignore:
Timestamp:
09/01/11 02:04:56 (9 months ago)
Author:
Alexander Trofimov
Message:

uploaders

Location:
trunk
Files:
14 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/contact.php

    r15338 r15476  
    9090                ), 
    9191            ), 
     92 
     93 
     94            'attachments' => array( 
     95                'type' => 'files', 
     96                'storage_object' => 'sample2', 
     97                'uploaders' => array ('Simple', 'HTML5'), 
     98                'name' => 'attachments', 
     99                'caption' => _t('_Attachments'), 
     100                'required' => true, 
     101            ), 
     102 
    92103            'captcha' => array( 
    93104                'type' => 'captcha', 
  • trunk/inc/classes/BxDolDb.php

    r15425 r15476  
    619619     * This function is usefull when you need to form array of parameters to pass to IN(...) SQL construction. 
    620620     * Example: 
    621      * \code 
     621     * @code 
    622622     * $a = array(2, 4.5, 'apple', 'car'); 
    623623     * $s = "SELECT * FROM `t` WHERE `a` IN (" . $oDb->implode_escape($a) . ")"; 
    624624     * echo $s; // outputs: SELECT * FROM `t` WHERE `a` IN (2, 4.5, 'apple', 'car') 
    625      * \endcode 
     625     * @endcode 
    626626     * 
    627627     * @param $mixed array or parameters or just one paramter 
  • trunk/inc/classes/BxDolStorage.php

    r15453 r15476  
    3333*/ 
    3434 
     35define('BX_DOL_STORAGE_ERR_NO_INPUT_METHOD', 1000); ///< there is such input method available 
    3536define('BX_DOL_STORAGE_ERR_NO_FILE', 1001); ///< there is no file to upload 
    3637define('BX_DOL_STORAGE_INVALID_FILE', 1002); ///< uploaded file is invalid or hack attempts 
     
    5354define('BX_DOL_STORAGE_DEFAULT_MIME_TYPE', 'octet/stream'); ///< default mime type if it is not find by extension 
    5455 
     56 
    5557bx_import('BxDolStorageQuery'); 
    5658 
     
    159161     * @return id of added file on success, false on error - to get exact error code call getErrorCode() 
    160162     */ 
    161     public function storeFile($sFilePath, $sName, $isPrivate = false, $iProfileId = 0) { } 
     163    public function storeFile($sMethod, $aMethodParams, $sName = false, $isPrivate = false, $iProfileId = 0) { 
     164 
     165        // setup input source using helper classes, like $_FILES or some URL for example 
     166 
     167        $sHelperClass = 'BxDolStorageHelper' . $sMethod; 
     168        if (!class_exists($sHelperClass)) { 
     169            $this->setErrorCode(BX_DOL_STORAGE_ERR_NO_INPUT_METHOD); 
     170            return false; 
     171        } 
     172 
     173        $oHelper = new $sHelperClass($aMethodParams); 
     174 
     175        // check for errors, like size and extentions checking 
     176 
     177        if ($iImmediateError = $oHelper->getImmediateError()) { 
     178            $this->setErrorCode($iImmediateError); 
     179            return false; 
     180        } 
     181 
     182        $sExt = $this->getFileExt($oHelper->getName()); 
     183        $sMimeType = $this->getMimeTypeByFileName($oHelper->getName()); 
     184 
     185        if (!$this->isValidExt($sExt)) { 
     186            $this->setErrorCode(BX_DOL_STORAGE_ERR_WRONG_EXT); 
     187            return false; 
     188        } 
     189 
     190        // before aupload callback + additional checking 
     191 
     192        if (!$this->onBeforeFileAdd (array( 
     193            'profile_id' => $iProfileId, 
     194            'file_name' => $oHelper->getName(), 
     195            'mime_type' => $sMimeType, 
     196            'ext' => $sExt, 
     197            'size' => $oHelper->getSize(), 
     198            'private' => $isPrivate ? 1 : 0, 
     199        ))) { 
     200            return false; 
     201        } 
     202 
     203        // create tmp file         
     204         
     205        $sTmpFile = $temp_file = tempnam(sys_get_temp_dir(), 'bxdol');; 
     206        if (!$oHelper->save($sTmpFile)) { 
     207            $this->setErrorCode(BX_DOL_STORAGE_INVALID_FILE); 
     208            return false; 
     209        } 
     210 
     211        // store file to storage engine 
     212 
     213        $sLocalId = $this->genRandName(); 
     214        $sPath = $this->genPath($sLocalId, $this->_aObject['levels']); 
     215        $sRemoteNamePath = $this->genRemoteNamePath ($sPath, $sLocalId, $sExt); 
     216 
     217        if (!$this->addFileToEngine($sTmpFile, $sLocalId, $oHelper->getName(), $isPrivate, $iProfileId)) { 
     218            unlink($sTmpFile); 
     219            $this->setErrorCode(BX_DOL_STORAGE_ERR_ENGINE_ADD); 
     220        } 
     221        unlink($sTmpFile); 
     222 
     223        // add record in db 
     224 
     225        $iTime = time(); 
     226        $iSize = $oHelper->getSize();         
     227        $bFileAdded = $this->_oDb->addFile($iProfileId, $sLocalId, $sRemoteNamePath, $oHelper->getName(), $sMimeType, $sExt, $iSize, $iTime, $isPrivate); 
     228        $iId = $this->_oDb->lastId(); 
     229        if (!$bFileAdded || !$iId) {         
     230            $this->deleteFileFromEngine($sPath . $sLocalId, $isPrivate); 
     231            $this->setErrorCode(BX_DOL_STORAGE_ERR_DB); 
     232            return false; 
     233        } 
     234             
     235        // after upload callback + triggers update 
     236     
     237        if (!$this->onFileAdded (array( 
     238            'id' => $iId, 
     239            'profile_id' => $iProfileId, 
     240            'remote_id' => $sLocalId, 
     241            'path' => $sPath . $sLocalId, 
     242            'file_name' => $oHelper->getName(), 
     243            'mime_type' => $sMimeType, 
     244            'size' => $iSize, 
     245            'private' => $isPrivate ? 1 : 0, 
     246        ))) { 
     247            $this->deleteFileFromEngine($sPath . $sLocalId, $isPrivate); 
     248            $this->_oDb->deleteFile($iId);             
     249            return false; 
     250        } 
     251 
     252        return $iId; 
     253    } 
     254 
     255    /** 
     256     * convert default multiple files array into more logical one 
     257     */ 
     258    public function convertMultipleFilesArray($aFiles) {  
     259         
     260        if (!is_array($aFiles) || !is_array($aFiles['name'])) 
     261            return false; 
     262        $aRet = array (); 
     263        foreach ($aFiles['name'] as $i => $sName) {             
     264            foreach ($aFiles as $sKey => $r) { 
     265                if (!$aFiles['name'][$i]) 
     266                    break; 
     267                $aRet[$i][$sKey] = $aFiles[$sKey][$i]; 
     268            }             
     269        } 
     270        return $aRet;     
     271    } 
    162272 
    163273    /** 
    164274     * the same as storeFile, but it tries to do it directly from uploaded file 
    165275     */ 
    166     public function storeUploadedFile($aFile, $isPrivate = false, $iProfileId = 0) { } 
     276    public function storeFileFromForm($aFile, $isPrivate = false, $iProfileId = 0) { 
     277        return $this->storeFile('Form', array('file' => $aFile), false, $isPrivate, $iProfileId); 
     278    } 
     279 
     280    /** 
     281     * the same as storeFile, but it tries to do it directly from HTML5 file upload method 
     282     */ 
     283    public function storeFileFromXhr($sName, $isPrivate = false, $iProfileId = 0) { 
     284        return $this->storeFile('Xhr', array('name' => $sName), false, $isPrivate, $iProfileId); 
     285    } 
    167286 
    168287    /** 
    169288     * Delete file by file id. 
    170289     */ 
    171     public function deleteFile($iFileId) { } 
     290    public function deleteFile($iFileId, $iProfileId = 0) {  
     291         
     292        $aFile = $this->_oDb->getFileById ($iFileId); 
     293        if (!$aFile) { 
     294            $this->setErrorCode(BX_DOL_STORAGE_ERR_FILE_NOT_FOUND); 
     295            return false; 
     296        } 
     297 
     298        if (!$this->onBeforeFileDelete ($aFile, $iProfileId)) { 
     299            return false; 
     300        } 
     301     
     302        if (!$this->deleteFileFromEngine($aFile['path'], $aFile['private'])) {  
     303            return false; 
     304        } 
     305 
     306        if (!$this->_oDb->deleteFile($aFile['id'])) { 
     307            $this->setErrorCode(BX_DOL_STORAGE_ERR_DB); 
     308            return false; 
     309        } 
     310 
     311        if (!$this->onFileDeleted ($aFile, $iProfileId)) { 
     312            return false; 
     313        } 
     314 
     315        return true; 
     316    } 
    172317 
    173318    /** 
     
    178323    public function getFileUrlById($iFileId) { } 
    179324 
     325    /** 
     326     * Get file info array by file id. 
     327     */  
     328    public function getFile($iFileId) { 
     329        return $this->_oDb->getFileById($iFileId); 
     330    } 
     331 
     332    /** 
     333     * Call this function after saving/associate just uploaded file id, so file is not ghost. 
     334     * Ghost files appear on download form automaticaly during next upload,  
     335     * for example if file was uploaded but was not submitted for some reason,  
     336     * so this mechanism ensure that file is not lost. 
     337     * @param $mixedFileIds array of file ids or just file id 
     338     * @param $iProfileId profile id 
     339     * @param return number of deleted ghost files 
     340     */ 
     341    public function afterUploadCleanup($mixedFileIds, $iProfileId) { 
     342        return $this->_oDb->deleteGhosts($mixedFileIds, $iProfileId); 
     343    } 
     344 
     345    public function getGhosts($iProfileId) { 
     346        return $this->_oDb->getGhosts($iProfileId); 
     347    }     
    180348 
    181349    public function tmpDebugGetFilesList() { 
    182350        $sQuery = "SELECT * FROM `" . $this->_aObject['table_files'] . "`"; 
    183351        return $this->_oDb->getAll($sQuery); 
     352    } 
     353 
     354    public function getRestrictionsTextExtensions ($iProfileId) { 
     355        switch ($this->_aObject['ext_mode']) { 
     356            case 'allow-deny': 
     357                if (!$this->_aObject['ext_allow']) 
     358                    return _t('_sys_storage_restriction_ext_all_denied'); 
     359                return _t('_sys_storage_restriction_ext_allowed', $this->_aObject['ext_allow']); 
     360            case 'deny-allow': 
     361                if (!$this->_aObject['ext_deny']) 
     362                    return _t('_sys_storage_restriction_ext_all_allowed'); 
     363                return _t('_sys_storage_restriction_ext_denied', $this->_aObject['ext_deny']); 
     364            default: 
     365                return _t('_sys_storage_restriction_ext_all_denied'); 
     366        } 
     367    } 
     368 
     369    public function getRestrictionsTextFileSize ($iProfileId) { 
     370        return _t('_sys_storage_restriction_size', _t_format_size($this->getMaxUploadFileSize($iProfileId))); 
     371    } 
     372 
     373    public function getRestrictionsTextArray ($iProfileId) { 
     374        $aTypes = array('Extensions', 'FileSize'); 
     375        $aRet = array(); 
     376        foreach ($aTypes as $sType) { 
     377            $sFunc = 'getRestrictionsText' . $sType; 
     378            $s = $this->$sFunc ($iProfileId); 
     379            if ($s) 
     380                $aRet[] = $s; 
     381        } 
     382        return $aRet; 
    184383    } 
    185384 
     
    237436        } 
    238437 
     438        if (!$this->_oDb->insertGhosts ($aFileInfo['id'], $aFileInfo['profile_id'])) { 
     439            $this->setErrorCode(BX_DOL_STORAGE_ERR_DB); 
     440            return false; 
     441        } 
     442 
    239443        $this->setErrorCode(BX_DOL_STORAGE_ERR_OK); 
    240444        $bRet = true;         
     
    269473        } 
    270474 
     475        $this->_oDb->deleteGhosts ($aFileInfo['id'], $aFileInfo['profile_id']); 
     476 
    271477        $this->setErrorCode(BX_DOL_STORAGE_ERR_OK); 
    272478        $bRet = true; 
     
    278484 
    279485    // ------------ internal functions 
    280  
    281     protected function storeUploadedFileBegin($aFile, $isPrivate = false, $iProfileId = 0) {  
    282  
    283         if (!$aFile['size'] || !$aFile['tmp_name']) { 
    284             $this->setErrorCode(BX_DOL_STORAGE_ERR_NO_FILE); 
    285             return false; 
    286         } 
    287  
    288         if (UPLOAD_ERR_OK != $aFile['error']) { 
    289             $this->setErrorCode((int)$aFile['error']); 
    290             return false; 
    291         } 
    292  
    293         $sExt = $this->getFileExt($aFile['name']); 
    294         $sMimeType = $this->getMimeTypeByFileName($aFile['name']); 
    295  
    296         if (!$this->isValidExt($sExt)) { 
    297             $this->setErrorCode(BX_DOL_STORAGE_ERR_WRONG_EXT); 
    298             return false; 
    299         } 
    300  
    301         if (!$this->onBeforeFileAdd (array( 
    302             'profile_id' => $iProfileId, 
    303             'file_name' => $aFile['name'], 
    304             'mime_type' => $sMimeType, 
    305             'ext' => $sExt, 
    306             'size' => $aFile['size'], 
    307             'private' => $isPrivate ? 1 : 0, 
    308         ))) { 
    309             return false; 
    310         } 
    311  
    312         return true; 
    313     } 
    314486 
    315487    protected function setErrorCode($i) { 
     
    335507            $sRet .= substr($s, 0, $i++) . '/'; 
    336508        return $sRet; 
     509    } 
     510 
     511    protected function genRemoteNamePath ($sPath, $sLocalId, $sExt) { 
     512        return $sPath . $sLocalId; 
    337513    } 
    338514 
     
    382558} 
    383559 
     560 
     561/** 
     562 * Handle file uploads via XMLHttpRequest 
     563 */ 
     564class BxDolStorageHelperXhr { 
     565 
     566    var $sName; 
     567 
     568    function BxDolStorageHelperXhr ($aParams) { 
     569        $this->sName = $aParams['name']; 
     570    } 
     571 
     572    function getImmediateError() { 
     573        return BX_DOL_STORAGE_ERR_OK; 
     574    } 
     575 
     576    function save($path) {     
     577        $input = fopen("php://input", "r"); 
     578        $temp = tmpfile(); 
     579        $realSize = stream_copy_to_stream($input, $temp); 
     580        fclose($input); 
     581         
     582        if (false === $this->getSize() || $realSize != $this->getSize()) { 
     583            return false; 
     584        } 
     585         
     586        $target = fopen($path, "w");         
     587        fseek($temp, 0, SEEK_SET); 
     588        stream_copy_to_stream($temp, $target); 
     589        fclose($target); 
     590         
     591        return true; 
     592    } 
     593 
     594    function getName() { 
     595        return $this->sName; 
     596    } 
     597 
     598    function getSize() { 
     599        if (isset($_SERVER["CONTENT_LENGTH"])) 
     600            return (int)$_SERVER["CONTENT_LENGTH"];             
     601        else 
     602            return false; 
     603    }    
     604} 
     605 
     606/** 
     607 * Handle file uploads via regular form post (uses the $_FILES array) 
     608 */ 
     609class BxDolStorageHelperForm {   
     610 
     611    var $aFile; 
     612 
     613    function BxDolStorageHelperForm ($aParams) { 
     614        $this->aFile = $aParams['file']; 
     615    } 
     616 
     617    function getImmediateError() { 
     618 
     619        if (!$this->aFile['size'] || !$this->aFile['tmp_name']) 
     620            return BX_DOL_STORAGE_ERR_NO_FILE; 
     621 
     622        if (UPLOAD_ERR_OK != $this->aFile['error']) 
     623            return (int)$this->aFile['error']; 
     624 
     625        return BX_DOL_STORAGE_ERR_OK; 
     626    } 
     627 
     628    function save($path) { 
     629        if (!move_uploaded_file($this->aFile['tmp_name'], $path)){ 
     630            return false; 
     631        } 
     632        return true; 
     633    } 
     634 
     635    function getName() { 
     636        return $this->aFile['name']; 
     637    } 
     638 
     639    function getSize() { 
     640        return $this->aFile['size']; 
     641    } 
     642} 
     643 
  • trunk/inc/classes/BxDolStorageLocal.php

    r15453 r15476  
    1919    public function BxDolStorageLocal($aObject) { 
    2020        parent::BxDolStorage($aObject); 
    21     } 
    22  
    23     /** 
    24      * Store file in the storage area. 
    25      * @param $sFilePath full path to the the file, with path and file, it maybe temporary uploaded file  
    26      * @param $sName file name with extention 
    27      * @param $isPrivate private or public file 
    28      * @return id of added file on success, false on error - to get exact error code call getErrorCode() 
    29      */ 
    30     public function storeFile($sFilePath, $sName, $isPrivate = false, $iProfileId = 0) { } 
    31  
    32     /** 
    33      * the same as storeFile, but it tries to do it directly from uploaded file 
    34      */ 
    35     public function storeUploadedFile($aFile, $isPrivate = false, $iProfileId = 0) {  
    36  
    37         if (!$this->storeUploadedFileBegin($aFile, $isPrivate, $iProfileId)) 
    38             return false; 
    39  
    40         $sExt = $this->getFileExt($aFile['name']); 
    41         $sMimeType = $this->getMimeTypeByFileName($aFile['name']); 
    42  
    43         $sLocalId = $this->genRandName(); 
    44         $sPath = $this->genPath($sLocalId, $this->_aObject['levels']); 
    45         $sNewFileDir = $this->getObjectBaseDir($isPrivate) . $sPath; 
    46         $sNewFilePath = $sNewFileDir . $sLocalId; 
    47  
    48         $this->mkdir($sNewFileDir); 
    49         if (!file_exists($sNewFileDir) || !is_writable($sNewFileDir)) { 
    50             $this->setErrorCode(BX_DOL_STORAGE_ERR_FILESYSTEM_PERM); 
    51             return false; 
    52         } 
    53          
    54         if (!move_uploaded_file($aFile['tmp_name'], $sNewFilePath)) { 
    55             $this->setErrorCode(BX_DOL_STORAGE_INVALID_FILE); 
    56             return false; 
    57         } 
    58  
    59         if (!chmod ($sNewFilePath, BX_DOL_STORAGE_FILE_RIGHTS)) { 
    60             unlink($sNewFilePath); 
    61             $this->setErrorCode(BX_DOL_STORAGE_ERR_ENGINE_ADD); 
    62             return false; 
    63         } 
    64  
    65         $iTime = time(); 
    66         $iSize = filesize($sNewFilePath); 
    67         if (!$this->_oDb->addFile($iProfileId, $sLocalId, $sPath . $sLocalId, $aFile['name'], $sMimeType, $sExt, $iSize, $iTime, $isPrivate)) { 
    68             unlink($sNewFilePath); 
    69             $this->setErrorCode(BX_DOL_STORAGE_ERR_DB); 
    70             return false; 
    71         } 
    72      
    73         $iId = $this->_oDb->lastId(); 
    74         if (!$iId) { 
    75             unlink($sNewFilePath); 
    76             $this->setErrorCode(BX_DOL_STORAGE_ERR_DB); 
    77             return false; 
    78         } 
    79  
    80         if (!$this->onFileAdded (array( 
    81             'id' => $iId, 
    82             'profile_id' => $iProfileId, 
    83             'remote_id' => $sLocalId, 
    84             'path' => $sPath . $sLocalId, 
    85             'file_name' => $aFile['name'], 
    86             'mime_type' => $sMimeType, 
    87             'size' => $iSize, 
    88             'private' => $isPrivate ? 1 : 0, 
    89         ))) { 
    90             $this->_oDb->deleteFile($iId); 
    91             unlink($sNewFilePath); 
    92             return false; 
    93         } 
    94  
    95         return $iId; 
    96     } 
    97  
    98     /** 
    99      * Delete file by file id. 
    100      */ 
    101     public function deleteFile($iFileId, $iProfileId = 0) {  
    102          
    103         $aFile = $this->_oDb->getFileById ($iFileId); 
    104         if (!$aFile) { 
    105             $this->setErrorCode(BX_DOL_STORAGE_ERR_FILE_NOT_FOUND); 
    106             return false; 
    107         } 
    108         
    109         $sFileLocation = $this->getObjectBaseDir($aFile['private']) . $aFile['path']; 
    110  
    111         if (!file_exists($sFileLocation)) { 
    112             $this->setErrorCode(BX_DOL_STORAGE_ERR_FILE_NOT_FOUND); 
    113             return false; 
    114         } 
    115  
    116         if (!$this->onBeforeFileDelete ($aFile, $iProfileId)) { 
    117             return false; 
    118         } 
    119          
    120         if (!unlink($sFileLocation)) { 
    121             $this->setErrorCode(BX_DOL_STORAGE_ERR_UNLINK); 
    122             return false; 
    123         } 
    124  
    125         if (!$this->_oDb->deleteFile($aFile['id'])) { 
    126             $this->setErrorCode(BX_DOL_STORAGE_ERR_DB); 
    127             return false; 
    128         } 
    129  
    130         if (!$this->onFileDeleted ($aFile, $iProfileId)) { 
    131             return false; 
    132         } 
    133  
    134         return true; 
    13521    } 
    13622 
     
    19076    // ----------------     
    19177 
     78    protected function addFileToEngine($sTmpFile, $sLocalId, $sName, $isPrivate, $iProfileId) { 
     79         
     80        $sPath = $this->genPath($sLocalId, $this->_aObject['levels']); 
     81        $sNewFileDir = $this->getObjectBaseDir($isPrivate) . $sPath; 
     82        $sNewFilePath = $sNewFileDir . $sLocalId; 
     83 
     84        $this->mkdir($sNewFileDir); 
     85        if (!file_exists($sNewFileDir) || !is_writable($sNewFileDir)) { 
     86            $this->setErrorCode(BX_DOL_STORAGE_ERR_FILESYSTEM_PERM); 
     87            return false; 
     88        } 
     89         
     90        if (!copy($sTmpFile, $sNewFilePath)) { 
     91            $this->setErrorCode(BX_DOL_STORAGE_ERR_ENGINE_ADD); 
     92            return false; 
     93        } 
     94 
     95        if (!chmod ($sNewFilePath, BX_DOL_STORAGE_FILE_RIGHTS)) { 
     96            unlink($sNewFilePath); 
     97            $this->setErrorCode(BX_DOL_STORAGE_ERR_ENGINE_ADD); 
     98            return false; 
     99        } 
     100 
     101        return true; 
     102    } 
     103 
     104    protected function deleteFileFromEngine($sFilePath, $isPrivate) {  
     105 
     106        $sFileLocation = $this->getObjectBaseDir($isPrivate) . $sFilePath; 
     107 
     108        if (!file_exists($sFileLocation)) { 
     109            $this->setErrorCode(BX_DOL_STORAGE_ERR_FILE_NOT_FOUND); 
     110            return false; 
     111        } 
     112 
     113        if (!unlink($sFileLocation)) { 
     114            $this->setErrorCode(BX_DOL_STORAGE_ERR_UNLINK); 
     115            return false; 
     116        } 
     117 
     118        return true; 
     119    } 
     120 
    192121    protected function getObjectBaseDir ($isPrivate = false) { 
    193122        return BX_DIRECTORY_STORAGE . $this->_aObject['object'] . '/'; 
  • trunk/inc/classes/BxDolStorageQuery.php

    r15452 r15476  
    4747        $sQuery = $this->prepare(" 
    4848            UPDATE `sys_objects_storage`  
    49             SET `current_size` = `current_size` + ?, `current_number` = `current_number` + ?, `ts` = ?  
     49            SET `current_size` = `current_size` + ?, `current_number` = `current_number` + (?), `ts` = ?  
    5050            WHERE `object` = ?",  
    5151            $iSize, $iNumber, $iTime, $this->_aObject['object'] 
     
    127127    } 
    128128 
     129    public function insertGhosts($mixedFileIds, $iProfileId) { 
     130 
     131        $iTime = time(); 
     132        if (!is_array($mixedFileIds)) 
     133            $mixedFileIds = array($mixedFileIds); 
     134         
     135        $iCount = 0; 
     136        foreach ($mixedFileIds as $iFileId) { 
     137            $sQuery = $this->prepare("INSERT INTO `sys_storage_ghosts` SET `id` = ?, `profile_id` = ?, `object` = ?, `created` = ?", $iFileId, $iProfileId, $this->_aObject['object'], $iTime); 
     138            $iCount += $this->query($sQuery); 
     139        } 
     140        return $iCount; 
     141    } 
     142 
     143    public function deleteGhosts($mixedFileIds, $iProfileId) { 
     144        $sQuery = $this->prepare("DELETE FROM `sys_storage_ghosts` WHERE `profile_id` = ? AND `object` = ? AND `id` IN (" . $this->implode_escape($mixedFileIds) . ")", $iProfileId, $this->_aObject['object']); 
     145        $iCount = $this->query($sQuery); 
     146        if ($iCount) 
     147            $this->query("OPTIMIZE TABLE `sys_storage_ghosts`"); 
     148        return $iCount; 
     149    } 
     150 
     151    public function getGhosts($iProfileId) { 
     152        $sQuery = $this->prepare("SELECT `f`.* FROM `sys_storage_ghosts` AS `g` INNER JOIN " . $this->_sTableFiles . " AS `f` ON (`f`.`id` = `g`.`id` AND `f`.`profile_id` = ?) WHERE `g`.`profile_id` = ? AND `g`.`object` = ?", $iProfileId, $iProfileId, $this->_aObject['object']); 
     153        return $this->getAll($sQuery); 
     154    } 
     155 
    129156    public function prune() { 
    130157        $iTime = time(); 
  • trunk/inc/classes/BxDolStorageS3.php

    r15453 r15476  
    4242 
    4343    /** 
    44      * Store file in the storage area. 
    45      * @param $sFilePath full path to the the file, with path and file, it maybe temporary uploaded file  
    46      * @param $sName file name with extention 
    47      * @param $isPrivate private or public file 
    48      * @return id of added file on success, false on error - to get exact error code call getErrorCode() 
    49      */ 
    50     public function storeFile($sFilePath, $sName, $isPrivate = false, $iProfileId = 0) { } 
    51  
    52     /** 
    53      * the same as storeFile, but it tries to do it directly from uploaded file 
    54      */ 
    55     public function storeUploadedFile($aFile, $isPrivate = false, $iProfileId = 0) {  
    56  
    57         if (!$this->storeUploadedFileBegin($aFile, $isPrivate, $iProfileId)) 
    58             return false; 
    59  
    60         $sExt = $this->getFileExt($aFile['name']); 
    61         $sMimeType = $this->getMimeTypeByFileName($aFile['name']); 
    62          
    63         $sLocalId = $this->genRandName(); 
    64         $sTmpFile = BX_DIRECTORY_PATH_TMP . $sLocalId; 
    65         $sPath = $this->genPath($sLocalId, $this->_aObject['levels']); 
    66         $sRemoteNamePath = $sPath . $sLocalId . '.' . $sExt; 
    67  
    68         if (!move_uploaded_file($aFile['tmp_name'], $sTmpFile)) { 
    69             $this->setErrorCode(BX_DOL_STORAGE_INVALID_FILE); 
    70             return false; 
    71         } 
    72         
    73         $aMetaHeaders = array(); 
    74         $aRequestHeaders = array ( 
    75             "Content-Type"  => $sMimeType, 
    76         ); 
    77         if ($this->_iCacheControl > 0) { 
    78             $aRequestHeaders = array_merge ($aRequestHeaders, array ( 
    79                 "Cache-Control" => "max-age=" . ($isPrivate && $this->_iCacheControl > $this->_aObject['token_life'] ? $this->_aObject['token_life'] : $this->_iCacheControl), 
    80             )); 
    81         } 
    82  
    83         $sStorageClass = $this->_bReducedRedundancy ? S3::STORAGE_CLASS_RRS : S3::STORAGE_CLASS_STANDARD; 
    84         $sACL = $isPrivate ? S3::ACL_AUTHENTICATED_READ : S3::ACL_PUBLIC_READ; 
    85         $aInputFile = $this->_s3->inputFile($sTmpFile);                         
    86         if (!$this->_s3->putObject($aInputFile, $this->_sBucket, $this->getObjectBaseDir($isPrivate) . $sRemoteNamePath, $sACL, $aMetaHeaders, $aRequestHeaders, $sStorageClass)) { 
    87             $this->setErrorCode(BX_DOL_STORAGE_ERR_ENGINE_ADD); 
    88             return false; 
    89         }                
    90  
    91         $iTime = time(); 
    92         $iSize = filesize($sTmpFile); 
    93         if (!$this->_oDb->addFile($iProfileId, $sLocalId, $sRemoteNamePath, $aFile['name'], $sMimeType, $sExt, $iSize, $iTime, $isPrivate)) { 
    94             $this->_s3->deleteObject($this->_sBucket, $this->getObjectBaseDir($isPrivate) . $sRemoteNamePath); 
    95             $this->setErrorCode(BX_DOL_STORAGE_ERR_DB); 
    96             return false; 
    97         } 
    98      
    99         $iId = $this->_oDb->lastId(); 
    100         if (!$iId) { 
    101             $this->_s3->deleteObject($this->_sBucket, $this->getObjectBaseDir($isPrivate) . $sRemoteNamePath); 
    102             $this->setErrorCode(BX_DOL_STORAGE_ERR_DB); 
    103             return false; 
    104         } 
    105  
    106         if (!$this->onFileAdded (array( 
    107             'id' => $iId, 
    108             'profile_id' => $iProfileId, 
    109             'remote_id' => $sLocalId, 
    110             'path' => $sRemoteNamePath, 
    111             'file_name' => $aFile['name'], 
    112             'mime_type' => $sMimeType, 
    113             'size' => $iSize, 
    114             'private' => $isPrivate ? 1 : 0, 
    115         ))) { 
    116             $this->_oDb->deleteFile($iId); 
    117             $this->_s3->deleteObject($this->_sBucket, $this->getObjectBaseDir($isPrivate) . $sRemoteNamePath); 
    118             return false; 
    119         } 
    120  
    121         return $iId; 
    122     } 
    123  
    124     /** 
    125      * Delete file by file id. 
    126      */ 
    127     public function deleteFile($iFileId, $iProfileId = 0) {  
    128          
    129         $aFile = $this->_oDb->getFileById ($iFileId); 
    130         if (!$aFile) { 
    131             $this->setErrorCode(BX_DOL_STORAGE_ERR_FILE_NOT_FOUND); 
    132             return false; 
    133         } 
    134  
    135         $sFileLocation = $this->getObjectBaseDir($aFile['private']) . $aFile['path']; 
    136  
    137         if (!$this->onBeforeFileDelete ($aFile, $iProfileId)) { 
    138             return false; 
    139         } 
    140          
    141         if (!$this->_s3->deleteObject($this->_sBucket, $sFileLocation)) { 
    142             $this->setErrorCode(BX_DOL_STORAGE_ERR_UNLINK); 
    143             return false; 
    144         } 
    145  
    146         if (!$this->_oDb->deleteFile($aFile['id'])) { 
    147             $this->setErrorCode(BX_DOL_STORAGE_ERR_DB); 
    148             return false; 
    149         } 
    150  
    151         if (!$this->onFileDeleted ($aFile, $iProfileId)) { 
    152             return false; 
    153         } 
    154  
    155         return true; 
    156     } 
    157  
    158     /** 
    15944     * Get file url, you need to override this to generate custom url for private files. 
    16045     * @param $iFileId file  
     
    18166    // ----------------     
    18267 
     68    protected function addFileToEngine($sTmpFile, $sLocalId, $sName, $isPrivate, $iProfileId) { 
     69 
     70        $sMimeType = $this->getMimeTypeByFileName($sName); 
     71        $sExt = $this->getFileExt($sName); 
     72        $sPath = $this->genPath($sLocalId, $this->_aObject['levels']); 
     73        $sRemoteNamePath = $sPath . $sLocalId . ($sExt ? '.' . $sExt : ''); 
     74 
     75        $aMetaHeaders = array(); 
     76        $aRequestHeaders = array ( 
     77            "Content-Type"  => $sMimeType, 
     78        ); 
     79        if ($this->_iCacheControl > 0) { 
     80            $aRequestHeaders = array_merge ($aRequestHeaders, array ( 
     81                "Cache-Control" => "max-age=" . ($isPrivate && $this->_iCacheControl > $this->_aObject['token_life'] ? $this->_aObject['token_life'] : $this->_iCacheControl), 
     82            )); 
     83        } 
     84 
     85        $sStorageClass = $this->_bReducedRedundancy ? S3::STORAGE_CLASS_RRS : S3::STORAGE_CLASS_STANDARD; 
     86        $sACL = $isPrivate ? S3::ACL_AUTHENTICATED_READ : S3::ACL_PUBLIC_READ; 
     87        $aInputFile = $this->_s3->inputFile($sTmpFile);                         
     88        if (!$this->_s3->putObject($aInputFile, $this->_sBucket, $this->getObjectBaseDir($isPrivate) . $sRemoteNamePath, $sACL, $aMetaHeaders, $aRequestHeaders, $sStorageClass)) { 
     89            $this->setErrorCode(BX_DOL_STORAGE_ERR_ENGINE_ADD); 
     90            return false; 
     91        }                
     92 
     93        return true; 
     94    } 
     95 
     96    protected function deleteFileFromEngine($sFilePath, $isPrivate) {  
     97 
     98        $sFileLocation = $this->getObjectBaseDir($isPrivate) . $sFilePath; 
     99         
     100        if (!$this->_s3->deleteObject($this->_sBucket, $sFileLocation)) { 
     101            $this->setErrorCode(BX_DOL_STORAGE_ERR_UNLINK); 
     102            return false; 
     103        } 
     104 
     105        return true; 
     106    } 
     107 
     108    protected function genRemoteNamePath ($sPath, $sLocalId, $sExt) { 
     109        return $sPath . $sLocalId . ($sExt ? '.' . $sExt : ''); 
     110    } 
     111 
    183112    protected function getObjectBaseDir ($isPrivate = false) { 
    184113        return $this->_aObject['object'] . '/'; 
  • trunk/inc/languages.inc.php

    r15470 r15476  
    490490    } 
    491491} 
     492 
     493function _t_format_size ($iSize) { 
     494    $a = array ( 
     495        1024 => '_sys_format_size_b',  
     496        1024*1024 => '_sys_format_size_kb', 
     497        1024*1024*1024 => '_sys_format_size_mb', 
     498        1024*1024*1024*1024 => '_sys_format_size_gb', 
     499        1024*1024*1024*1024*1024 => '_sys_format_size_tb', 
     500    );     
     501    foreach ($a as $i => $sKey) 
     502        if ($iSize < $i) 
     503            return _t($sKey, round($iSize / ($i / 1024), 1)); 
     504    return _t('_sys_format_size_b', 0); 
     505} 
  • trunk/install/langs/lang-en.php

    r15472 r15476  
    8484    '_Error' => 'Error', 
    8585    '_Explanation' => 'Explanation', 
     86    '_Failed' => 'Failed', 
    8687    '_FAQ' => 'FAQ', 
    8788    '_Female' => 'Woman', 
     
    28402841    '_adm_mobile_page_homepage' => 'Homepage', 
    28412842    '_adm_mobile_page_profile' => 'Profile', 
     2843 
     2844    '_sys_format_size_b' => '{0} bytes', 
     2845    '_sys_format_size_kb' => '{0} Kb', 
     2846    '_sys_format_size_mb' => '{0} Mb', 
     2847    '_sys_format_size_gb' => '{0} Gb', 
     2848    '_sys_format_size_tb' => '{0} Tb', 
     2849 
     2850    '_sys_storage_restriction_ext_all_allowed' => 'Files of any type are allowed.', 
     2851    '_sys_storage_restriction_ext_all_denied' => 'Sorry, all file types are restricted for now', 
     2852    '_sys_storage_restriction_ext_allowed' => 'Only files with the following types are allowed: {0}', 
     2853    '_sys_storage_restriction_ext_denied' => 'All file types are allowed, except the following: {0}', 
     2854 
     2855    '_sys_storage_restriction_size' => 'Max file size is {0}', 
     2856 
     2857    '_sys_uploader_confirm_leaving_page' => 'Upload is is progress! Leaving the page means abort uploading!', 
     2858    '_sys_uploader_confirm_close_popup' => 'Are you sure? It may cancel files uploading.', 
     2859    '_sys_uploader_upload_canceled' => 'Upload was canceled',     
     2860 
     2861    '_sys_uploader_simple_button_name' => 'Simple Upload', 
     2862    '_sys_uploader_simple_title'  => 'Simple Upload', 
     2863    '_sys_uploader_simple_submit_button' => 'Upload', 
     2864    '_sys_uploader_simple_attach_one_more_file' => '+ Add more files', 
     2865 
     2866    '_sys_uploader_html5_title'  => 'Multiple Upload', 
     2867    '_sys_uploader_html5_button_name' => 'Multiple Upload', 
     2868    '_sys_uploader_html5_shoose_file' => 'Choose a file', 
     2869    '_sys_uploader_html5_drop_area' => 'Drop files here to upload', 
    28422870); 
    28432871?> 
  • trunk/install/sql/v70.sql

    r15472 r15476  
    36903690) ENGINE=MyISAM DEFAULT CHARSET=utf8; 
    36913691 
     3692CREATE TABLE IF NOT EXISTS `sys_storage_ghosts` ( 
     3693  `id` int(11) NOT NULL, 
     3694  `profile_id` int(10) unsigned NOT NULL, 
     3695  `object` varchar(32) NOT NULL, 
     3696  `created` int(10) unsigned NOT NULL, 
     3697  UNIQUE KEY `id` (`id`,`object`) 
     3698) ENGINE=MyISAM DEFAULT CHARSET=utf8; 
     3699 
    36923700CREATE TABLE IF NOT EXISTS `sys_storage_mime_types` ( 
    36933701  `ext` varchar(32) NOT NULL, 
  • trunk/templates/base/popup_box.html

    r15474 r15476  
    2121            <div class="bx-clear"></div> 
    2222        </div> 
    23         <div class="bx-db-content bx-def-padding-sec">__content__</div> 
     23        <div class="bx-db-content bx-def-padding">__content__</div> 
    2424    </div> 
    2525</div> 
  • trunk/templates/base/scripts/BxBaseFormView.php

    r15332 r15476  
    161161 
    162162            case 'select_box': 
    163                 $sRow = $this->genRowSelectBox($aInput); 
     163                $sRow = $this->genRowCustom($aInput, 'genInputSelectBox'); 
     164            break; 
     165 
     166            case 'files': 
     167                $sRow = $this->genRowCustom($aInput, 'genInputFiles'); 
    164168            break; 
    165169 
     
    188192        $sErrorIcon = $this->genErrorIcon(empty($aInput['error']) ? '' : $aInput['error']); 
    189193 
    190         $aInput['tr_attrs']['class'] = "bx-form-element-wrapper bx-def-margin-sec-top" . (isset($aInput['tr_attrs']['class']) ? ' ' . $aInput['tr_attrs']['class'] : ''); 
     194        $aInput['tr_attrs']['class'] = "bx-form-element-wrapper bx-def-margin-top" . (isset($aInput['tr_attrs']['class']) ? ' ' . $aInput['tr_attrs']['class'] : ''); 
    191195        if (isset($aInput['name'])) 
    192196            $aInput['tr_attrs']['id'] = "bx-form-element-" . $aInput['name']; 
     
    256260     * @return string 
    257261     */ 
    258     function genRowSelectBox(&$aInput) { 
     262    function genRowCustom(&$aInput, $sCustomMethod) { 
    259263 
    260264        $sCaption = isset($aInput['caption']) ? bx_process_output($aInput['caption']) : ''; 
     
    265269        $sInfoIcon = !empty($aInput['info']) ? $this->genInfoIcon($aInput['info']) : ''; 
    266270 
    267         $sErrorIcon = $this->genErrorIcon(empty($aInput['error']) ? '' : $aInput['error']); 
    268         $sInput = $this->genInputSelectBox($aInput, $sInfoIcon, $sErrorIcon); 
    269  
    270         $aInput['tr_attrs']['class'] = "bx-form-element-wrapper bx-def-margin-sec-top" . (isset($aInput['tr_attrs']['class']) ? ' ' . $aInput['tr_attrs']['class'] : ''); 
     271        $sErrorIcon = $this->genErrorIcon(empty($aInput['error']) ? '' : $aInput['error']);         
     272        $sInput = $this->$sCustomMethod($aInput, $sInfoIcon, $sErrorIcon); 
     273 
     274        $aInput['tr_attrs']['class'] = "bx-form-element-wrapper bx-def-margin-top" . (isset($aInput['tr_attrs']['class']) ? ' ' . $aInput['tr_attrs']['class'] : ''); 
    271275        if (isset($aInput['name'])) 
    272276            $aInput['tr_attrs']['id'] = "bx-form-element-" . $aInput['name']; 
     
    280284                    </div> 
    281285 
    282                     <div class="value$sClassAdd"> 
     286                    <div class="bx-form-value$sClassAdd"> 
    283287                        <div class="clear_both"></div> 
    284288                            $sInput 
     
    482486 
    483487        // add default className to attributes 
    484         $aAttrs['class'] = "bx-def-font-inputs bx-form-input-{$aInput['type']}" . (isset($aAttrs['class']) ? ' ' . $aAttrs['class'] : ''); 
     488        $aAttrs['class'] = "bx-def-font-inputs bx-form-input-{$aInput['type']}" . ('submit' == $aInput['type'] ? ' bx-btn bx-btn-primary' : '') . (isset($aAttrs['class']) ? ' ' . $aAttrs['class'] : ''); 
    485489        $aAttrs['type'] = $aInput['type']; 
    486490        if (isset($aInput['name'])) $aAttrs['name'] = $aInput['name']; 
     
    497501        $sAttrs = $this->convertArray2Attrs($aAttrs); 
    498502 
    499         return  "<input $sAttrs />\n"; 
    500  
     503        if ('submit' == $aInput['type']) 
     504            return  "<button $sAttrs>" . $aInput['value'] . "</button>\n"; 
     505        else 
     506            return  "<input $sAttrs />\n"; 
    501507    } 
    502508 
     
    648654 
    649655    /** 
     656     * Generate Select Box Element 
     657     * 
     658     * @param array $aInput 
     659     * @return string 
     660     */ 
     661    function genInputFiles(&$aInput, $sInfo = '', $sError = '') { 
     662 
     663         
     664 
     665/* 
     666TODO:  
     667    HTML for showing uploaded file (it should be overridable by specific storage engine, like handling file uploads)  
     668*/ 
     669 
     670        $sUniqId = genRndPwd (8, false); 
     671        $sUploaders = ''; 
     672        $oUploader = null; 
     673        foreach ($aInput['uploaders'] as $sUploaderObject) { 
     674            bx_import('BxDolUploader'); 
     675            $oUploader = BxDolUploader::getObjectInstance($sUploaderObject, $aInput['storage_object'], $sUniqId); 
     676            if (!$oUploader) 
     677                continue; 
     678            $sUploaders .= $oUploader->getUploaderButton(); 
     679        }                 
     680 
     681        $sInitGhosts = isset($aInput['init_ghosts']) && !$aInput['init_ghosts'] ? '' : $oUploader->getNameJsInstanceUploader() . '.restoreGhosts();'; 
     682 
     683        // TODO: move HTML to templates 
     684        return  
     685            '<div class="bx-form-input-files-uploaders bx-def-margin-sec-top">' . $sUploaders . '<div class="bx-clear">&nbsp;</div></div>' .  
     686            $sInfo . 
     687            '<div id="' . $oUploader->getIdContainerErrors() . '" class="bx-form-input-files-errors bx-def-margin-sec-top">&nbsp;</div>' .  
     688            '<div id="' . $oUploader->getIdContainerResult() . '" class="bx-form-input-files-result bx-def-margin-sec-top">&nbsp;</div>' .  
     689            '<script>$(document).ready(function(){' . $sInitGhosts . '});</script>'; 
     690    } 
     691 
     692    /** 
    650693     * Generate Multiple Select Element 
    651694     * 
     
    915958 
    916959            if ($aAttrs and is_array($aAttrs)) { 
    917                 $aAttrs['class'] = "bx-form-section" . (isset($aAttrs['class']) ? (' ' . $aAttrs['class']) : ''); 
     960                $aAttrs['class'] = "bx-form-section bx-def-padding bx-def-color-bg-sec" . (isset($aAttrs['class']) ? (' ' . $aAttrs['class']) : ''); 
    918961                $sAttrs = $this->convertArray2Attrs($aAttrs); 
    919962            } else { 
    920                 $sAttrs = ' class="bx-form-section bx-def-padding-sec bx-def-color-bg-sec" '; 
     963                $sAttrs = ' class="bx-form-section bx-def-padding bx-def-color-bg-sec" '; 
    921964            } 
    922965 
Note: See TracChangeset for help on using the changeset viewer.