| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554 |
- <?php
- /**
- * The model file of file module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
- * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author Chunsheng Wang <chunsheng@cnezsoft.com>
- * @package file
- * @version $Id: model.php 4976 2013-07-02 08:15:31Z wyd621@gmail.com $
- * @link https://www.zentao.net
- */
- ?>
- <?php
- class fileModel extends model
- {
- public $savePath = '';
- public $webPath = '';
- public $now = 0;
- /**
- * Construct function.
- *
- * @access public
- * @return void
- */
- public function __construct()
- {
- parent::__construct();
- $this->now = time();
- $this->setSavePath();
- $this->setWebPath();
- }
- /**
- * Get files of an object.
- *
- * @param string $objectType
- * @param int|array $objectID
- * @param string $extra
- * @access public
- * @return array
- */
- public function getByObject($objectType, $objectID, $extra = '')
- {
- $files = $this->dao->select('*')->from(TABLE_FILE)
- ->where('objectType')->eq($objectType)
- ->andWhere('objectID')->in($objectID)
- ->andWhere('extra')->ne('editor')
- ->beginIF($extra)->andWhere('extra')->in($extra)->fi()
- ->andWhere('deleted')->eq('0')
- ->orderBy('id')
- ->fetchAll('id');
- foreach($files as $file) $this->setFileWebAndRealPaths($file);
- return $files;
- }
- /**
- * 按照objectID分组获取附件列表。
- * Get files of an object group by objectID.
- *
- * @param string $objectType
- * @param string|array $objectID
- * @access public
- * @return array
- */
- public function groupByObjectID($objectType, $objectID)
- {
- $fileGroup = $this->dao->select('*')->from(TABLE_FILE)
- ->where('objectType')->eq($objectType)
- ->andWhere('objectID')->in($objectID)
- ->andWhere('deleted')->eq('0')
- ->orderBy('id')
- ->fetchGroup('objectID', 'id');
- foreach($fileGroup as $objectID => $files)
- {
- foreach($files as $file) $this->setFileWebAndRealPaths($file);
- }
- return $fileGroup;
- }
- /**
- * Delete files by object.
- *
- * @param string $objectType
- * @param int $objectID
- * @access public
- * @return bool
- */
- public function deleteByObject($objectType, $objectID)
- {
- $files = $this->dao->select('*')->from(TABLE_FILE)
- ->where('objectType')->eq($objectType)
- ->andWhere('objectID')->in($objectID)
- ->andWhere('deleted')->eq('0')
- ->fetchAll('id');
- foreach($files as $file)
- {
- $this->dao->update(TABLE_FILE)->set('deleted')->eq(1)->where('id')->eq($file->id)->exec();
- }
- return true;
- }
- /**
- * Get info of a file.
- *
- * @param int $fileID
- * @access public
- * @return object|false
- */
- public function getById($fileID)
- {
- $file = $this->dao->findById($fileID)->from(TABLE_FILE)->fetch();
- if(empty($file)) return false;
- $this->setFileWebAndRealPaths($file);
- return $file;
- }
- /**
- * Get file by gid.
- *
- * @param string $gid
- * @access public
- * @return string
- */
- public function getByGid($gid)
- {
- $file = $this->dao->select('*')->from(TABLE_FILE)
- ->where('gid')->eq($gid)
- ->orWhere('(gid')->eq('')
- ->andWhere('title')->eq($gid)
- ->markRight(1)
- ->fetch();
- if(empty($file)) return false;
- $this->setFileWebAndRealPaths($file);
- return $file;
- }
- /**
- * Get file by object.
- *
- * @param string $objectType
- * @param int $objectID
- * @param string $title
- * @param string $extra
- * @access public
- * @return object|false
- */
- public function query($objectType, $objectID = 0, $title = '', $extra = '')
- {
- $file = $this->dao->select('*')->from(TABLE_FILE)
- ->where('objectType')->eq($objectType)
- ->beginIF($objectID)->andWhere('objectID')->eq($objectID)->fi()
- ->beginIF($title)->andWhere('title')->eq($title)->fi()
- ->beginIF($extra)->andWhere('extra')->eq($extra)->fi()
- ->fetch();
- if(empty($file)) return false;
- return $file;
- }
- /**
- * Get files by ID list.
- *
- * @param string|array $fileIdList
- * @access public
- * @return array
- */
- public function getByIdList($fileIdList)
- {
- if(empty($fileIdList)) return array();
- $files = $this->dao->select('*')->from(TABLE_FILE)->where('id')->in($fileIdList)->orderBy('id')->fetchAll('id');
- foreach($files as $file) $this->setFileWebAndRealPaths($file);
- return $files;
- }
- /**
- * Save upload.
- *
- * @param string $objectType
- * @param int $objectID
- * @param int|string $extra
- * @param string $filesName
- * @param string $labelsName
- * @access public
- * @return array
- */
- public function saveUpload($objectType = '', $objectID = 0, $extra = '', $filesName = 'files', $labelsName = 'labels')
- {
- $fileTitles = array();
- $now = helper::today();
- $files = $this->getUpload($filesName, $labelsName);
- foreach($files as $file)
- {
- if(!isset($file['size']) || $file['size'] == 0) continue;
- if(!move_uploaded_file($file['tmpname'], $this->savePath . $this->getSaveName($file['pathname']))) return false;
- $file = $this->compressImage($file);
- $file['objectType'] = $objectType;
- $file['objectID'] = $objectID;
- $file['addedBy'] = $this->app->user->account;
- $file['addedDate'] = $now;
- if($extra) $file['extra'] = $extra;
- unset($file['tmpname']);
- $this->dao->insert(TABLE_FILE)->data($file)->exec();
- $fileTitles[$this->dao->lastInsertId()] = $file['title'];
- }
- return $fileTitles;
- }
- /**
- * Save a file.
- *
- * @param array $file
- * @param string $objectType
- * @param int $objectID
- * @param string $extra
- * @param string $filesName
- * @param string $labelsName
- * @access public
- * @return object
- */
- public function saveAFile($file, $objectType = '', $objectID = 0, $extra = '', $filesName = 'files', $labelsName = 'labels')
- {
- $now = helper::today();
- if(!move_uploaded_file($file['tmpname'], $this->savePath . $this->getSaveName($file['pathname']))) return false;
- $file = $this->compressImage($file);
- $file['objectType'] = $objectType;
- $file['objectID'] = $objectID;
- $file['addedBy'] = $this->app->user->account;
- $file['addedDate'] = $now;
- $file['extra'] = $extra;
- unset($file['tmpname']);
- $this->dao->insert(TABLE_FILE)->data($file)->exec();
- $fileTitle = new stdclass();
- $fileTitle->id = $this->dao->lastInsertId();
- $fileTitle->title = $file['title'];
- return $fileTitle;
- }
- /**
- * Get counts of uploaded files.
- *
- * @access public
- * @return int
- */
- public function getCount()
- {
- return count($this->getUpload());
- }
- /**
- * Get info of uploaded files.
- *
- * @param string $htmlTagName
- * @param string $labelsName
- * @access public
- * @return array
- */
- public function getUpload($htmlTagName = 'files', $labelsName = 'labels')
- {
- $files = array();
- if(!isset($_FILES[$htmlTagName])) return $files;
- if(!is_array($_FILES[$htmlTagName]['error']) && $_FILES[$htmlTagName]['error'] != 0) return $_FILES[$htmlTagName];
- if(is_array($_FILES[$htmlTagName]['error']) && reset($_FILES[$htmlTagName]['error']) != 0)
- {
- $_FILES[$htmlTagName]['error'] = reset($_FILES[$htmlTagName]['error']);
- return $_FILES[$htmlTagName];
- }
- $purifier = $this->app->loadClass('purifier');
- /* If the file var name is an array. */
- if(is_array($_FILES[$htmlTagName]['name']))
- {
- extract($_FILES[$htmlTagName]);
- foreach($name as $id => $filename)
- {
- if(empty($filename)) continue;
- if(!validater::checkFileName($filename)) continue;
- $title = isset($_POST[$labelsName][$id]) ? $_POST[$labelsName][$id] : '';
- $file['extension'] = $this->getExtension($filename, $tmp_name[$id]);
- $file['pathname'] = $this->setPathName($id, $file['extension']);
- $file['title'] = (!empty($title) and $title != $filename) ? htmlSpecialString($title) : $filename;
- $file['title'] = $purifier->purify($file['title']);
- $file['size'] = $size[$id];
- $file['tmpname'] = $tmp_name[$id];
- $file['extra'] = !empty($extra[$id]) ? $extra[$id] : '';
- $files[] = $file;
- }
- }
- else
- {
- if(empty($_FILES[$htmlTagName]['name'])) return $files;
- extract($_FILES[$htmlTagName]);
- if(!validater::checkFileName($name)) return array();
- $title = isset($_POST[$labelsName][0]) ? $_POST[$labelsName][0] : '';
- $file['extension'] = $this->getExtension($name, $tmp_name);
- $file['pathname'] = $this->setPathName(0, $file['extension']);
- $file['title'] = (!empty($title) && $title != $name) ? htmlSpecialString($title) : $name;
- $file['title'] = $purifier->purify($file['title']);
- $file['size'] = $size;
- $file['tmpname'] = $tmp_name;
- return array($file);
- }
- return $files;
- }
- /**
- * get uploaded file from zui.uploader.
- *
- * @access public
- * @return array
- */
- public function getChunkedFile()
- {
- $name = urldecode(zget($_SERVER, 'HTTP_X_FILENAME', ''));
- if(!validater::checkFileName($name) or empty($name)) return array();
- $purifier = $this->app->loadClass('purifier');
- $file = array();
- $file['id'] = 0;
- $file['extension'] = $this->getExtension($name);
- $file['title'] = $purifier->purify(substr($name, 0, strpos($name, $file['extension']) - 1));
- $file['size'] = zget($_SERVER, 'HTTP_X_FILESIZE', 0);
- $file['pathname'] = md5($file['title']);
- $file['chunks'] = zget($_SERVER, 'HTTP_X_TOTAL_CHUNKS', 0);
- $file['chunkIndex'] = zget($_SERVER, 'HTTP_X_CHUNK_INDEX', 0);
- if(stripos($this->config->file->allowed, ",{$file['extension']},") === false) $file['pathname'] = $file['pathname'] . '.notAllowed';
- return $file;
- }
- /**
- * Save uploaded file by chunk.
- *
- * @param array $file
- * @param string $uid
- * @access public
- * @return array
- */
- public function saveChunkedFile($file, $uid)
- {
- if($file['chunks'] == 0) return array();
- $tmpFilePath = $this->app->getTmpRoot() . 'uploadfiles/';
- $tmpFileSavePath = $tmpFilePath . $uid . '/';
- if(!is_dir($tmpFileSavePath)) mkdir($tmpFileSavePath, 0777, true);
- $file['realpath'] = $tmpFileSavePath . basename($this->getSaveName($file['pathname']));
- file_put_contents($file['realpath'], file_get_contents('php://input'), $file['chunkIndex'] == 0 ? 0 : FILE_APPEND);
- $uploadFile = array();
- $uploadFile['extension'] = $file['extension'];
- $uploadFile['pathname'] = $file['pathname'];
- $uploadFile['title'] = $file['title'];
- $uploadFile['realpath'] = $file['realpath'];
- $uploadFile['size'] = $file['size'];
- return $uploadFile;
- }
- /**
- * Get extension of a file.
- *
- * @param string $filename
- * @param string $filePath
- * @access public
- * @return string
- */
- public function getExtension($filename, $filePath = '')
- {
- $extension = trim(strtolower(pathinfo($filename, PATHINFO_EXTENSION)));
- if($extension and strpos($extension, '::') !== false) $extension = substr($extension, 0, strpos($extension, '::'));
- if(in_array($extension, $this->config->file->imageExtensions) && !empty($filePath))
- {
- $imagesize = getimagesize($filePath);
- if(!isset($imagesize[2])) return 'txt';
- $realExtension = image_type_to_extension($imagesize[2], false);
- $extension = $extension == 'jpg' && $realExtension == 'jpeg' ? 'jpg' : $realExtension;
- }
- if(empty($extension) or stripos(",{$this->config->file->dangers},", ",{$extension},") !== false) return 'txt';
- if(empty($extension) or stripos(",{$this->config->file->allowed},", ",{$extension},") === false) return 'txt';
- if($extension == 'php') return 'txt';
- return $extension;
- }
- /**
- * Get save name.
- *
- * @param string $pathName
- * @access public
- * @return string
- */
- public function getSaveName($pathName)
- {
- $position = strrpos($pathName, '.');
- return $position === false ? $pathName : substr($pathName, 0, $position);
- }
- /**
- * Get real path name.
- *
- * @param string $pathName
- * @access public
- * @return string
- */
- public function getRealPathName($pathName)
- {
- $realPath = $this->savePath . $pathName;
- if(file_exists($realPath)) return $pathName;
- return $this->getSaveName($pathName);
- }
- /**
- * Get export tpl.
- *
- * @param string $module
- * @access public
- * @return array
- */
- public function getExportTemplate($module)
- {
- return $this->dao->select('id,title,content,public')->from(TABLE_USERTPL)
- ->where('type')->eq("export$module")
- ->andwhere('account', true)->eq($this->app->user->account)
- ->orWhere('public')->eq('1')
- ->markRight(1)
- ->orderBy('id')
- ->fetchAll();
- }
- /**
- * Get tmp import path.
- *
- * @access public
- * @return string
- */
- public function getPathOfImportedFile()
- {
- $path = $this->app->getTmpRoot() . 'import';
- if(!is_dir($path)) mkdir($path, 0755, true);
- return $path;
- }
- /**
- * Save export template.
- *
- * @param string $module
- * @access public
- * @return int|false
- */
- public function saveExportTemplate($module)
- {
- $template = fixer::input('post')
- ->add('account', $this->app->user->account)
- ->add('type', "export$module")
- ->join('content', ',')
- ->get();
- if($template->title == $this->lang->file->defaultTPL)
- {
- dao::$errors[] = sprintf($this->lang->error->unique, $this->lang->file->tplTitle, $this->lang->file->defaultTPL);
- return false;
- }
- $condition = "`type`='export$module' and account='{$this->app->user->account}'";
- $this->dao->insert(TABLE_USERTPL)->data($template)->batchCheck('title, content', 'notempty')->check('title', 'unique', $condition)->exec();
- return $this->dao->lastInsertId();
- }
- /**
- * Set path name of the uploaded file to be saved.
- *
- * @param string|int $fileID
- * @param string $extension
- * @access public
- * @return string
- */
- public function setPathName($fileID, $extension)
- {
- $sessionID = session_id();
- $randString = substr($sessionID, mt_rand(0, strlen($sessionID) - 5), 3);
- return date('Ym/dHis', $this->now) . $fileID . mt_rand(0, 10000) . $randString . '.' . $extension;
- }
- /**
- * Set save path.
- *
- * @access public
- * @return void
- */
- public function setSavePath()
- {
- $companyID = isset($this->app->company->id) ? $this->app->company->id : 1;
- $savePath = $this->app->getAppRoot() . "www/data/upload/{$companyID}/" . date('Ym/', $this->now);
- $parentDir = dirname($savePath);
- while(!isset($parentCanWrite))
- {
- if(file_exists($parentDir)) $parentCanWrite = is_writable($parentDir);
- $parentDir = dirname($parentDir);
- }
- if(!file_exists($savePath) && $parentCanWrite)
- {
- mkdir($savePath, 0777, true);
- touch($savePath . 'index.html');
- }
- $this->savePath = dirname($savePath) . '/';
- }
- /**
- * Set the web path of upload files.
- *
- * @access public
- * @return void
- */
- public function setWebPath()
- {
- $companyID = isset($this->app->company->id) ? $this->app->company->id : 1;
- $this->webPath = $this->app->getWebRoot() . "data/upload/{$companyID}/";
- }
- /**
- * Set paths: realPath and webPath.
- *
- * @param object $file
- * @access public
- * @return void
- */
- public function setFileWebAndRealPaths($file)
- {
- if($file->objectType == 'traincourse' or $file->objectType == 'traincontents')
- {
- $file->realPath = $this->app->getWwwRoot() . 'data/course/' . $file->pathname;
- $file->webPath = $this->config->webRoot . 'data/course/' . $file->pathname;
- }
- else
- {
- $pathName = $this->getRealPathName($file->pathname);
- $file->realPath = $this->savePath . $pathName;
- $file->webPath = $this->webPath . $pathName;
- }
- if(!isset($file->name)) $file->name = $file->title;
- if(!isset($file->url)) $file->url = helper::createLink('file', 'download', "fileID={$file->id}");
- }
- /**
- * Insert the set image size code.
- *
- * @param string|null $content
- * @param int $maxSize
- * @access public
- * @return string|null
- */
- public function setImgSize($content, $maxSize = 0)
- {
- $content = (string)$content;
- if(empty($content)) return $content;
- static $fileLink, $imageLink;
- if(empty($fileLink)) $fileLink = helper::createLink('file', 'read', 'fileID=(%fileID%)', '\w+');
- if(empty($imageLink)) $imageLink = helper::createLink('file', 'read', "fileID=$1", "$3");
- $readLinkReg = str_replace(array('%fileID%', '/', '.', '?'), array('[0-9]+', '\/', '\.', '\?'), $fileLink);
- $content = preg_replace('/ src="(' . $readLinkReg . ')" /', ' onload="setImageSize(this,' . $maxSize . ')" src="$1" ', $content);
- $content = preg_replace('/ src="{([0-9]+)(\.(\w+))?}" /', ' onload="setImageSize(this,' . $maxSize . ')" src="' . $imageLink . '" ', $content);
- return str_replace(' src="data/upload', ' onload="setImageSize(this,' . $maxSize . ')" src="data/upload', $content);
- }
- /**
- * Check file exists or not.
- *
- * @param object $file
- * @access public
- * @return bool
- */
- public function fileExists($file)
- {
- if(empty($file->realPath)) return false;
- return file_exists($file->realPath);
- }
- /**
- * Unlink file.
- *
- * @param object $file
- * @access public
- * @return bool|null
- */
- public function unlinkFile($file)
- {
- if(empty($file->realPath)) return false;
- return @unlink($file->realPath);
- }
- /**
- * Replace a file.
- *
- * @access public
- * @return bool
- * @param int $fileID
- * @param string $postName
- */
- public function replaceFile($fileID, $postName = 'upFile')
- {
- $files = $this->getUpload($postName);
- if(empty($files)) return false;
- $pathName = $this->dao->select('pathname')->from(TABLE_FILE)->where('id')->eq($fileID)->fetch('pathname');
- if(empty($pathName)) return false;
- $file = $files[0];
- $realPathName = $this->savePath . $this->getRealPathName($pathName);
- $parentDir = dirname($realPathName);
- if(!is_dir($parentDir) and is_writable(dirname($parentDir))) mkdir($parentDir);
- move_uploaded_file($file['tmpname'], $realPathName);
- $file['pathname'] = $pathName;
- $file = $this->compressImage($file);
- $fileInfo = new stdclass();
- $fileInfo->addedBy = $this->app->user->account;
- $fileInfo->addedDate = helper::now();
- $fileInfo->size = $file['size'];
- $this->dao->update(TABLE_FILE)->data($fileInfo)->where('id')->eq($fileID)->exec();
- return true;
- }
- /**
- * Check file priv.
- *
- * @param object $file
- * @access public
- * @return bool
- */
- public function checkPriv($file)
- {
- if(!$file->objectType || !$file->objectID) return true;
- if(!$this->loadModel('user')->isLogon()) return true;
- if($file->extra == 'editor') return true;
- $objectType = $file->objectType;
- $objectID = $file->objectID;
- $table = zget($this->config->objectTables, $objectType, '');
- if(!$table) return true;
- $groupName = zget($this->config->file->objectGroup, $objectType, '');
- if(!empty($groupName))
- {
- $groupID = $this->dao->findByID($objectID)->from($table)->fetch($groupName);
- if($objectType == 'testcase' && $groupID == 0) return true;
- return $this->loadModel($groupName)->checkPriv((int)$groupID);
- }
- if($objectType == 'build')
- {
- $build = $this->dao->select('project,execution')->from(TABLE_BUILD)->where('id')->eq($objectID)->fetch();
- if($build->execution) return $this->loadModel('execution')->checkPriv($build->execution);
- return $this->loadModel('project')->checkPriv($build->project);
- }
- if($objectType == 'release')
- {
- $release = $this->dao->select('project,product')->from(TABLE_RELEASE)->where('id')->eq($objectID)->fetch();
- return $this->loadModel('product')->checkPriv($release->product);
- }
- if($objectType == 'doc')
- {
- $doc = $this->dao->findById($objectID)->from(TABLE_DOC)->fetch();
- return $this->loadModel('doc')->checkPrivDoc($doc);
- }
- if($objectType == 'feedback')
- {
- $productID = $this->dao->findById($objectID)->from(TABLE_FEEDBACK)->fetch('product');
- $grantProducts = $this->loadModel('feedback')->getGrantProducts();
- return in_array($productID, array_keys($grantProducts));
- }
- return true;
- }
- /**
- * Compress image to config configured size.
- *
- * @param string $rawImage
- * @param string $target
- * @param int $x
- * @param int $y
- * @param int $width
- * @param int $height
- * @param int $resizeWidth
- * @param int $resizeHeight
- * @access public
- * @return void
- */
- public function cropImage($rawImage, $target, $x, $y, $width, $height, $resizeWidth = 0, $resizeHeight = 0)
- {
- $this->app->loadClass('phpthumb', true);
- if(!extension_loaded('gd')) return false;
- $croper = new phpthumb($rawImage);
- if($resizeWidth > 0) $croper->resize($resizeWidth, $resizeHeight);
- $croper->crop($x, $y, $width, $height);
- $croper->save($target);
- }
- /**
- * Paste image in kindeditor at firefox and chrome.
- *
- * @param string $data
- * @param string $uid
- * @param bool $safe
- * @access public
- * @return string
- */
- public function pasteImage($data, $uid = '', $safe = false)
- {
- if(empty($data)) return '';
- $dataLength = strlen($data);
- if(ini_get('pcre.backtrack_limit') < $dataLength) ini_set('pcre.backtrack_limit', $dataLength);
- preg_match_all('/<img src="(data:image\/(\S+);base64,(\S+))".*\/>/U', $data, $out);
- if($out[3])
- {
- foreach($out[3] as $key => $base64Image)
- {
- $base64Image = str_replace('\"', '"', $base64Image);
- $extension = strtolower($out[2][$key]);
- if(!in_array($extension, $this->config->file->imageExtensions)) helper::end();
- $imageData = base64_decode($base64Image);
- $file['extension'] = $extension;
- $file['pathname'] = $this->setPathName($key, $file['extension']);
- $file['size'] = strlen($imageData);
- $file['addedBy'] = $this->app->user->account;
- $file['addedDate'] = helper::today();
- $file['title'] = str_replace(".$extension", '', basename($file['pathname']));
- $imagePath = $this->savePath . $this->getSaveName($file['pathname']);
- if(is_writable(dirname($imagePath))) file_put_contents($imagePath, $imageData);
- $this->dao->insert(TABLE_FILE)->data($file)->exec();
- $fileID = $this->dao->lastInsertID();
- if($uid) $_SESSION['album'][$uid][] = $fileID;
- $data = str_replace($out[1][$key], helper::createLink('file', 'read', "fileID=$fileID", $file['extension']), $data);
- }
- }
- elseif($safe)
- {
- $data = fixer::stripDataTags(rawurldecode($data));
- }
- return $data;
- }
- /**
- * Parse CSV.
- *
- * @param string $csvFile
- * @access public
- * @return array
- */
- public function parseCSV($csvFile)
- {
- /* Parse file only in zentao. */
- if(strpos($csvFile, $this->app->getBasePath()) !== 0) return array();
- if(!file_exists($csvFile)) return array();
- $fh = fopen($csvFile, "r");
- $data = array();
- while(($row = fgetcsv($fh, 0, ",", "\"", "\\")) !== false) $data[] = $row;
- fclose($fh);
- return $data;
- }
- /**
- * Process editor.
- *
- * @param object $data
- * @param string|array $editorList
- * @param mixed $uid
- * @access public
- * @return object
- */
- public function processImgURL($data, $editorList, $uid = '')
- {
- if(!is_string($uid)) return $data;
- if(is_string($editorList)) $editorList = explode(',', str_replace(' ', '', $editorList));
- if(empty($editorList)) return $data;
- $readLinkReg = helper::createLink('file', 'read', 'fileID=(%fileID%)', '(%viewType%)');
- $readLinkReg = str_replace(array('%fileID%', '%viewType%', '?', '/'), array('[0-9]+', '\w+', '\?', '\/'), $readLinkReg);
- $imageIdList = array();
- foreach($editorList as $editorID)
- {
- if(empty($editorID) or empty($data->$editorID)) continue;
- $imgURL = $this->config->requestType == 'GET' ? '{$2.$1}' : '{$1.$2}';
- $content = $this->pasteImage($data->$editorID, $uid);
- if($content) $data->$editorID = $content;
- $data->$editorID = preg_replace("/ src=\"$readLinkReg\" /", ' src="' . $imgURL . '" ', $data->$editorID);
- $data->$editorID = preg_replace("/ src=\"" . htmlSpecialString($readLinkReg) . "\" /", ' src="' . $imgURL . '" ', $data->$editorID);
- preg_match_all('/ src="{([0-9]+)\.\w+}"/', $data->$editorID, $matches);
- if($matches[1])
- {
- foreach($matches[1] as $imageID) $imageIdList[$imageID] = $imageID;
- }
- }
- if(!empty($_SESSION['album'][$uid]))
- {
- foreach($_SESSION['album'][$uid] as $imageID)
- {
- if(isset($imageIdList[$imageID])) $_SESSION['album']['used'][$uid][$imageID] = $imageID;
- }
- }
- return $data;
- }
- /**
- * Compress image
- *
- * @param array $file
- * @access public
- * @return array
- */
- public function compressImage($file)
- {
- if(!extension_loaded('gd') or !function_exists('imagecreatefromjpeg')) return $file;
- $pathName = $file['pathname'];
- $fileName = $this->savePath . $this->getSaveName($pathName);
- $suffix = $file['extension'];
- $lowerSuffix = strtolower($suffix);
- if(!in_array($lowerSuffix, $this->config->file->image2Compress)) return $file;
- $quality = 85;
- $newSuffix = '.jpg';
- $compressedName = str_replace($suffix, $newSuffix, $pathName);
- $res = $lowerSuffix == '.bmp' ? $this->imagecreatefrombmp($fileName) : imagecreatefromjpeg($fileName);
- imagejpeg($res, $fileName, $quality);
- $file['pathname'] = $compressedName;
- $file['extension'] = ltrim($newSuffix, '.');
- $file['size'] = filesize($fileName);
- return $file;
- }
- /**
- * Read 24bit BMP files
- * Author: de77
- * Licence: MIT
- * Webpage: de77.com
- * Version: 07.02.2010
- * Source : https://github.com/acustodioo/pic/blob/master/imagecreatefrombmp.function.php
- *
- * @param string $filename
- * @access public
- * @return resource
- */
- public function imagecreatefrombmp($filename)
- {
- $f = fopen($filename, "rb");
- //read header
- $header = fread($f, 54);
- $header = unpack('c2identifier/Vfile_size/Vreserved/Vbitmap_data/Vheader_size/'.
- 'Vwidth/Vheight/vplanes/vbits_per_pixel/Vcompression/Vdata_size/'.
- 'Vh_resolution/Vv_resolution/Vcolors/Vimportant_colors', $header);
- if ($header['identifier1'] != 66 or $header['identifier2'] != 77) return false;
- if ($header['bits_per_pixel'] != 24) return false;
- $wid2 = ceil((3 * $header['width']) / 4) * 4;
- $wid = $header['width'];
- $hei = $header['height'];
- $img = imagecreatetruecolor($header['width'], $header['height']);
- //read pixels
- for($y = $hei - 1; $y >= 0; $y--)
- {
- $row = fread($f, $wid2);
- $pixels = str_split($row, 3);
- for ($x = 0; $x < $wid; $x++) imagesetpixel($img, $x, $y, $this->dwordize($pixels[$x]));
- }
- fclose($f);
- return $img;
- }
- /**
- * Dwordize for imagecreatefrombmp
- *
- * @param string $str
- * @access private
- * @return int
- */
- private function dwordize($str)
- {
- $a = ord($str[0]);
- $b = ord($str[1]);
- $c = ord($str[2]);
- return $c * 256 * 256 + $b * 256 + $a;
- }
- /**
- * Update objectID.
- *
- * @param array|string|bool $uid
- * @param int $objectID
- * @param string $objectType
- * @access public
- * @return bool
- */
- public function updateObjectID($uid, $objectID, $objectType)
- {
- if(empty($uid)) return true;
- if(is_string($uid)) $uid = array($uid);
- if(!is_array($uid)) return true;
- foreach($uid as $value)
- {
- if(empty($_SESSION['album']['used'][$value])) continue;
- $data = new stdclass();
- $data->objectID = $objectID;
- $data->objectType = $objectType;
- if(!defined('RUN_MODE') || RUN_MODE != 'api') $data->extra = 'editor';
- $this->dao->update(TABLE_FILE)->data($data)->where('id')->in($_SESSION['album']['used'][$value])->exec();
- }
- return !dao::isError();
- }
- /**
- * Get upload by uid.
- *
- * @param array|string|bool $uid
- * @param string $filesName
- * @param string $labelsName
- * @access public
- * @return array
- */
- public function getUploadByUID($uid, $filesName = 'files', $labelsName = 'labels')
- {
- if(empty($uid)) return array();
- if(is_string($uid)) $uid = array($uid);
- if(!is_array($uid)) return array();
- $files = array();
- foreach($uid as $value)
- {
- if(empty($_SESSION['album']['used'][$value])) continue;
- $uidFiles = $this->dao->select('id, title')->from(TABLE_FILE)->where('id')->in($_SESSION['album']['used'][$value])->fetchPairs();
- foreach($uidFiles as $fileID => $fileName)
- {
- $files[$fileID] = $fileName;
- }
- }
- return $files;
- }
- /**
- * Revert real src.
- *
- * @param object $data
- * @param string $fields
- * @access public
- * @return object
- */
- public function replaceImgURL($data, $fields)
- {
- $moduleName = $this->app->getModuleName();
- $methodName = $this->app->getMethodName();
- if($moduleName == 'story' && isset($data->type)) $moduleName = $data->type;
- if(is_string($fields)) $fields = explode(',', str_replace(' ', '', $fields));
- $textareaFields = $this->dao->select('id,field')->from(TABLE_WORKFLOWFIELD)->where('module')->eq($moduleName)->andWhere('control')->eq('richtext')->andWhere('buildin')->eq('0')->fetchPairs();
- if($textareaFields) $fields = array_merge($fields, $textareaFields);
- foreach($fields as $field)
- {
- if(empty($field) or empty($data->$field)) continue;
- if(is_numeric($data->$field)) $data->$field = (string)$data->$field;
- $data->$field = preg_replace('/ src="{([0-9]+)(\.(\w+))?}" /', ' src="' . helper::createLink('file', 'read', "fileID=$1", "$3") . '" ', $data->$field);
- /* Convert plain text URLs into HTML hyperlinks. */
- if(isset($this->config->file->convertURL['common'][$methodName]) or isset($this->config->file->convertURL[$moduleName][$methodName]))
- {
- $fieldData = $data->$field;
- preg_match_all('/(<a[^>]*>.*<\/a>)/Ui', $fieldData, $aTags);
- preg_match_all('/(<img[^>]*>)/i', $fieldData, $imgTags);
- preg_match_all('/(<iframe[^>]*>[^<]*<\/iframe>)/i', $fieldData, $iframeTags);
- preg_match_all('/(<embed[^>]*>)/i', $fieldData, $embedTags);
- preg_match_all('/(<pre[^>]*>.*<\/pre>)/sUi', $fieldData, $preTags);
- foreach($aTags[0] as $i => $aTag) $fieldData = str_replace($aTag, "<A_{$i}>", $fieldData);
- foreach($imgTags[0] as $i => $imgTag) $fieldData = str_replace($imgTag, "<IMG_{$i}>", $fieldData);
- foreach($iframeTags[0] as $i => $iframeTag) $fieldData = str_replace($iframeTag, "<IFRAME_{$i}>", $fieldData);
- foreach($embedTags[0] as $i => $embedTag) $fieldData = str_replace($embedTag, "<EMBED_{$i}>", $fieldData);
- foreach($preTags[0] as $i => $preTag) $fieldData = str_replace($preTag, "<PRE_{$i}>", $fieldData);
- $fieldData = preg_replace('/(http:\/\/|https:\/\/)((\w|=|\?|\.|\/|\&|-|%|;)+)/i', "<a href=\"\\0\" target=\"_blank\">\\0</a>", $fieldData);
- foreach($aTags[0] as $i => $aTag) $fieldData = str_replace("<A_{$i}>", $aTag, $fieldData);
- foreach($imgTags[0] as $i => $imgTag) $fieldData = str_replace("<IMG_{$i}>", $imgTag, $fieldData);
- foreach($iframeTags[0] as $i => $iframeTag) $fieldData = str_replace("<IFRAME_{$i}>", $iframeTag, $fieldData);
- foreach($embedTags[0] as $i => $embedTag) $fieldData = str_replace("<EMBED_{$i}>", $embedTag, $fieldData);
- foreach($preTags[0] as $i => $preTag) $fieldData = str_replace("<PRE_{$i}>", $preTag, $fieldData);
- $data->$field = $fieldData;
- }
- }
- return $data;
- }
- /**
- * Auto delete useless image.
- *
- * @param string $uid
- * @access public
- * @return void
- */
- public function autoDelete($uid)
- {
- if(empty($_SESSION['album'][$uid])) return;
- foreach($_SESSION['album'][$uid] as $imageID)
- {
- if(isset($_SESSION['album']['used'][$uid][$imageID])) continue;
- $file = $this->getById($imageID);
- if(empty($file)) continue;
- $this->dao->delete()->from(TABLE_FILE)->where('id')->eq($imageID)->exec();
- $this->unlinkFile($file);
- }
- unset($_SESSION['album'][$uid]);
- }
- /**
- * Send the download header to the client.
- *
- * @param string $fileName
- * @param string $fileType
- * @param string $content
- * @access public
- * @return void
- * @param string $type
- */
- public function sendDownHeader($fileName, $fileType, $content, $type = 'content')
- {
- /* Clean the ob content to make sure no space or utf-8 bom output. */
- $obLevel = ob_get_level();
- for($i = 0; $i < $obLevel; $i++) ob_end_clean();
- /* Set the downloading cookie, thus the export form page can use it to judge whether to close the window or not. */
- helper::setcookie('downloading', 1, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
- /* Append the extension name auto. */
- $extension = $fileType ? ('.' . $fileType) : '';
- if($extension && strpos(strtolower($fileName), $extension) === false) $fileName .= $extension;
- /* Judge the content type. */
- $mimes = $this->config->file->mimes;
- $contentType = isset($mimes[$fileType]) ? $mimes[$fileType] : $mimes['default'];
- /* Safari浏览器下载文件名乱码问题。 */
- if(isset($_SERVER['CONTENT_TYPE']) && isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['CONTENT_TYPE'] == 'application/x-www-form-urlencoded' && preg_match("/Safari/", $_SERVER["HTTP_USER_AGENT"]))
- {
- $fileName = rawurlencode($fileName);
- $attachment = 'attachment; filename*=utf-8\'\'' . $fileName;
- }
- else
- {
- $fileName = str_replace("+", "%20", urlencode($fileName));
- $attachment = "attachment; filename=\"{$fileName}\";";
- }
- helper::header('Content-type', $contentType);
- helper::header('Content-Disposition', $attachment);
- helper::header('Pragma', 'no-cache');
- helper::header('Expires', '0');
- if($type == 'content') helper::end($content);
- if($type == 'file' and file_exists($content))
- {
- if(stripos($content, $this->app->getBasePath()) !== 0) helper::end();
- set_time_limit(0);
- $chunkSize = 10 * 1024 * 1024;
- $handle = fopen($content, "r");
- while(!feof($handle)) echo fread($handle, $chunkSize);
- fclose($handle);
- helper::end();
- }
- }
- /**
- * Get image size.
- *
- * @param object $file
- * @access public
- * @return array|false
- */
- public function getImageSize($file)
- {
- if(empty($file->realPath)) return array();
- if($this->config->file->storageType == 'fs')
- {
- return file_exists($file->realPath) ? getimagesize($file->realPath) : array(0, 0, $file->extension);
- }
- elseif($this->config->file->storageType == 's3')
- {
- $this->app->loadClass('ossclient', true);
- $config = $this->config->file;
- $ossClient = new ossclient($config->accessKeyId, $config->accessKeySecret, $config->endpoint, $config->bucket);
- $info = $ossClient->getImageInfo($file->pathname);
- return array($info->ImageWidth->value, $info->ImageHeight->value, 'img');
- }
- }
- /**
- * Get file pairs.
- *
- * @param string $idList
- * @param string $value
- * @access public
- * @return array
- */
- public function getPairs($idList, $value = 'title')
- {
- return $this->dao->select("id,$value")->from(TABLE_FILE)->where('id')->in($idList)->fetchPairs();
- }
- /**
- * Update test case version.
- *
- * @param object $file
- * @access public
- * @return void
- */
- public function updateTestcaseVersion($file)
- {
- $oldCase = $this->dao->select('*')->from(TABLE_CASE)->where('fromCaseID')->eq($file->objectID)->fetch();
- if(empty($oldCase)) return;
- $isLibCase = $oldCase->lib && empty($oldCase->product);
- if($isLibCase)
- {
- $fromcaseVersion = $oldCase->fromCaseVersion + 1;
- $this->dao->update(TABLE_CASE)->set('`fromCaseVersion`')->eq($fromcaseVersion)->where('`fromCaseID`')->eq($file->objectID)->exec();
- }
- }
- /**
- * Update story files.
- *
- * @param int $storyID
- * @access public
- * @return void
- */
- public function updateStoryFiles($storyID)
- {
- $storySpec = $this->dao->select('id')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->orderBy('id desc')->limit(1)->fetch();
- if(empty($storySpec)) return;
- $files = $this->dao->select('id')->from(TABLE_FILE)
- ->where('objectType')->eq('story')
- ->andWhere('objectID')->eq($storyID)
- ->orderBy('id')
- ->fetchAll();
- $storyFiles = [];
- foreach($files as $file) $storyFiles[] = $file->id;
- $this->dao->update(TABLE_STORYSPEC)->set('files')->eq(implode(',', $storyFiles))->where('id')->eq($storySpec->id)->exec();
- }
- /**
- * Process file info for object.
- *
- * @param string $objectType
- * @param object $oldObject
- * @param object $newObject
- * @param string $extra
- * @param string $filesName
- * @param string $labelsName
- * @access public
- * @return void
- */
- public function processFile4Object($objectType, $oldObject, $newObject, $extra = '', $filesName = 'files', $labelsName = 'labels')
- {
- if(empty($oldObject->id)) return;
- $oldFiles = empty($oldObject->files) ? '' : implode(',', array_keys($oldObject->files));
- $deleteFiles = $newObject->deleteFiles ?? null;
- if(!empty($deleteFiles))
- {
- if(!isset($this->config->file->logicalDeletionType[$objectType]))
- {
- $this->dao->delete()->from(TABLE_FILE)->where('id')->in($deleteFiles)->exec();
- foreach($deleteFiles as $fileID)
- {
- $this->unlinkFile($oldObject->files[$fileID]);
- $oldFiles = empty($oldFiles) ? '' : trim(str_replace(",$fileID,", ',', ",$oldFiles,"), ',');
- }
- }
- else
- {
- foreach($deleteFiles as $fileID)
- {
- $this->dao->update(TABLE_FILE)->set('deleted')->eq(1)->where('id')->eq($fileID)->exec();
- $oldFiles = empty($oldFiles) ? '' : trim(str_replace(",$fileID,", ',', ",$oldFiles,"), ',');
- }
- }
- }
- $this->updateObjectID($this->post->uid, $oldObject->id, $objectType);
- $addedFiles = $this->saveUpload($objectType, $oldObject->id, $extra, $filesName, $labelsName);
- $addedFiles = empty($addedFiles) ? '' : ',' . implode(',', array_keys($addedFiles));
- $newObject->files = trim($oldFiles . $addedFiles, ',');
- $oldObject->files = $oldFiles;
- }
- /**
- * Print file in view/edit page.
- *
- * @param object $file
- * @param string $method
- * @param bool $showDelete
- * @param bool $showEdit
- * @param object|null $object
- * @access public
- * @return string
- */
- public function printFile($file, $method, $showDelete, $showEdit, $object)
- {
- $html = '';
- $sessionString = session_name() . '=' . session_id();
- $uploadDate = $this->lang->file->uploadDate . substr($file->addedDate, 0, 10);
- $fileTitle = "<i class='icon icon-file-text'></i> " . $file->title;
- $fileSize = helper::formatKB((float)$file->size);
- if(strpos($file->title, ".{$file->extension}") === false && $file->extension != 'txt') $fileTitle .= ".{$file->extension}";
- $imageWidth = 0;
- if(stripos('jpg|jpeg|gif|png|bmp', $file->extension) !== false)
- {
- $imageSize = $this->getImageSize($file);
- $imageWidth = $imageSize[0] ?? 0;
- }
- $downloadLink = helper::createLink('file', 'download', "fileID=$file->id");
- $downloadLink .= strpos($downloadLink, '?') === false ? '?' : '&';
- $downloadLink .= $sessionString;
- $fileTitleLink = common::hasPriv('file', 'download') ? html::a($downloadLink, $fileTitle . " <span class='text-gray'>({$fileSize})</span>", '_blank', "id='fileTitle$file->id'") : "<div id='fileTitle$file->id' style='display: inline-block'>" . $fileTitle . " <span class='text-gray'>({$fileSize})</span></div>";
- $objectType = zget($this->config->file->objectType, $file->objectType);
- $viewMethod = $objectType == 'feedback' && $this->config->vision != 'lite' ? 'adminView' : 'view';
- $html .= "<li class='mb-2 file' title='{$uploadDate}'>" . $fileTitleLink;
- if(strpos('view,edit', $method) !== false)
- {
- if(common::hasPriv($objectType, $viewMethod, $object)) $html = $this->buildFileActions($html, $downloadLink, $imageWidth, $showEdit, $showDelete, $file, $object);
- }
- else
- {
- if(common::hasPriv($objectType, 'edit', $object))
- {
- $html .= "<span class='right-icon'> ";
- if(common::hasPriv('file', 'edit')) $html .= html::a(helper::createLink('file', 'edit', "fileID=$file->id"), $this->lang->file->edit, '', "data-width='400' class='fileAction btn btn-link' title='{$this->lang->file->edit}'");
- if(common::hasPriv('file', 'delete')) $html .= html::a('###', $this->lang->delete, '', "class='fileAction btn btn-link' onclick='deleteFile($file->id)' title='{$this->lang->delete}'");
- $html .= '</span>';
- }
- }
- $html .= '</li>';
- return $html;
- }
- /**
- * Build file actions.
- *
- * @param string $html
- * @param string $downloadLink
- * @param bool $showEdit
- * @param bool $showEdit
- * @param bool $showDelete
- * @param object $file
- * @param object|null $object
- * @access public
- * @return string
- * @param int $imageWidth
- */
- public function buildFileActions($html, $downloadLink, $imageWidth, $showEdit, $showDelete, $file, $object)
- {
- $objectType = zget($this->config->file->objectType, $file->objectType);
- $html .= "<span class='right-icon hidden'> ";
- /* Determines whether the file supports preview. */
- if($file->extension == 'txt')
- {
- $extension = 'txt';
- if(($position = strrpos($file->title, '.')) !== false) $extension = substr($file->title, $position + 1);
- $file->extension = $extension;
- }
- /* For the open source version of the file judgment. */
- $canPreview = false;
- $officeTypes = 'doc|docx|xls|xlsx|ppt|pptx|pdf';
- $isOfficeFile = stripos($officeTypes, $file->extension) !== false;
- if(stripos('txt|jpg|jpeg|gif|png|bmp|mp4', $file->extension) !== false) $canPreview = true;
- if(isset($this->config->file->libreOfficeTurnon) and $this->config->file->libreOfficeTurnon == 1 && $isOfficeFile) $canPreview = true;
- if($canPreview && common::hasPriv('file', 'preview'))
- {
- $dataToggle = $isOfficeFile ? '' : " data-toggle='modal' data-size='lg'";
- $html .= html::a(helper::createLink('file', 'preview', "fileID=$file->id&mouse=left"), "<i class='icon icon-eye'></i>", $isOfficeFile ? '_blank' : '', "class='fileAction btn btn-link text-primary' title='{$this->lang->file->preview}' {$dataToggle}");
- }
- if(common::hasPriv('file', 'download')) $html .= html::a($downloadLink, "<i class='icon icon-download'></i>", '_blank', "class='fileAction btn btn-link text-primary' title='{$this->lang->file->downloadFile}'");
- if(common::hasPriv($objectType, 'edit', $object))
- {
- if($showEdit and common::hasPriv('file', 'edit')) $html .= html::a('###', "<i class='icon icon-pencil-alt'></i>", '', "id='renameFile$file->id' class='fileAction btn btn-link edit text-primary' onclick='showRenameBox($file->id)' title='{$this->lang->file->edit}'");
- if($showDelete and common::hasPriv('file', 'delete')) $html .= html::a('###', "<i class='icon icon-trash'></i>", '', "class='fileAction btn btn-link text-primary' onclick='deleteFile($file->id, this)' title='{$this->lang->delete}'");
- }
- $html .= '</span>';
- $html .= '</li>';
- $fileTitle = $file->title;
- if(strrpos($fileTitle, '.') !== false)
- {
- /* Fix the file name exe.exe */
- $title = explode('.', $fileTitle);
- $extension = end($title);
- if($file->extension == 'txt' && $extension != $file->extension) $file->extension = $extension;
- array_pop($title);
- $fileTitle = implode('.', $title);
- }
- $html .= "<li class='file hidden'><div>";
- $html .= "<div class='renameFile w-300px' id='renameBox{$file->id}'><i class='icon icon-file-text'></i>";
- $html .= "<div class='input-group'>";
- $html .= "<input type='text' id='fileName{$file->id}' value='{$fileTitle}' class='form-control'/>";
- $html .= "<input type='hidden' id='extension{$file->id}' value='{$file->extension}'/>";
- $html .= "<strong class='input-group-addon'>.{$file->extension}</strong></div>";
- $html .= "<div class='input-group-btn'>";
- $html .= "<button type='button' class='btn btn-success file-name-confirm' onclick='setFileName({$file->id})' style='border-radius: 0px 2px 2px 0px; border-left-color: transparent;'><i class='icon icon-check'></i></button>";
- $html .= "<button type='button' class='btn btn-gray file-name-cancel' onclick='showFile({$file->id})' style='border-radius: 0px 2px 2px 0px; border-left-color: transparent;'><i class='icon icon-close'></i></button>";
- $html .= '</div></div></div></li>';
- return $html;
- }
- /**
- * Get last modified timestamp of file.
- *
- * @param object $file
- * @access public
- * @return int|false
- */
- public function fileMTime($file)
- {
- if(empty($file->realPath) or !file_exists($file->realPath)) return false;
- return filemtime($file->realPath);
- }
- /**
- * Get file size.
- *
- * @param object $file
- * @access public
- * @return int
- */
- public function fileSize($file)
- {
- if(empty($file->realPath) or !file_exists($file->realPath)) return false;
- return filesize($file->realPath);
- }
- /**
- * Save file to local storage temporarily.
- *
- * @param object $file
- * @access public
- * @return string
- */
- public function saveAsTempFile($file)
- {
- if(empty($file->realPath)) return '';
- /* If the storage type is local, do nothing. */
- if($this->config->file->storageType == 'fs') return $file->realPath;
- return '';
- }
- /**
- * 保存默认文件。
- * Save default files.
- *
- * @param array $fileList
- * @param string $objectType
- * @param int|array $objectID
- * @param string|int $extra
- * @access public
- * @param int|mixed[] $objectIdList
- */
- public function saveDefaultFiles($fileList, $objectType, $objectIdList, $extra = '')
- {
- if(empty($fileList)) return;
- if(is_int($objectIdList)) $objectIdList = array($objectIdList);
- if(!empty($_POST['deleteFiles']))
- {
- foreach($this->post->deleteFiles as $deletedFileID) unset($fileList[$deletedFileID]);
- }
- if(!empty($_POST['renameFiles']))
- {
- foreach($this->post->renameFiles as $renamedFileID => $newName) $fileList[$renamedFileID]['title'] = $newName;
- }
- foreach($objectIdList as $objectID)
- {
- $fileIdList = '';
- foreach($fileList as $file)
- {
- unset($file['id']);
- $file['objectType'] = $objectType;
- $file['objectID'] = $objectID;
- $file['extra'] = $extra;
- $fileIdList .= ',' . $this->fileTao->saveFile($file, 'url,deleted,realPath,webPath,name,url');
- }
- if($objectType == 'story') $this->dao->update(TABLE_STORYSPEC)->set("files = CONCAT(files, '{$fileIdList}')")->where('story')->eq($objectID)->exec();
- }
- foreach($objectIdList as $objectID)
- {
- $uid = $this->post->uid ? $this->post->uid : '';
- $this->updateObjectID($uid, $objectID, $objectType);
- $this->saveUpload($objectType, $objectID, $extra);
- }
- }
- /**
- * Process file differcences for object.
- *
- * @param string $objectType
- * @param object $oldObject
- * @param object $newObject
- * @param string $extra
- * @param string $filesName
- * @param string $labelsName
- * @access public
- * @return void
- */
- public function processFileDiffsForObject($objectType, $oldObject, $newObject, $extra = '', $filesName = 'files', $labelsName = 'labels')
- {
- if(empty($oldObject->id)) return;
- $deleteFiles = array();
- if(!empty($newObject->deleteFiles))
- {
- if(!isset($this->config->file->logicalDeletionType[$objectType]))
- {
- $this->dao->delete()->from(TABLE_FILE)->where('id')->in($newObject->deleteFiles)->exec();
- foreach($newObject->deleteFiles as $fileID)
- {
- if(!isset($oldObject->{$filesName}[$fileID])) continue;
- $this->unlinkFile($oldObject->{$filesName}[$fileID]);
- $deleteFiles[] = isset($oldObject->{$filesName}[$fileID]) ? $oldObject->{$filesName}[$fileID]->title : '';
- }
- }
- else
- {
- $this->dao->update(TABLE_FILE)->set('deleted')->eq(1)->where('id')->in($newObject->deleteFiles)->exec();
- foreach($newObject->deleteFiles as $fileID) $deleteFiles[$fileID] = isset($oldObject->{$filesName}[$fileID]) ? $oldObject->{$filesName}[$fileID]->title : '';
- }
- }
- $renameFiles = array();
- if(!empty($newObject->renameFiles))
- {
- foreach($newObject->renameFiles as $renamedFileID => $newName)
- {
- $this->dao->update(TABLE_FILE)->set('title')->eq($newName)->where('id')->in($renamedFileID)->exec();
- $renameFiles[$renamedFileID] = array('old' => isset($oldObject->{$filesName}[$renamedFileID]) ? $oldObject->{$filesName}[$renamedFileID]->title : '', 'new' => $newName);
- }
- }
- $addedFiles = $this->saveUpload($objectType, $oldObject->id, $extra, $filesName, $labelsName);
- if(defined('RUN_MODE') && RUN_MODE === 'api')
- {
- $uidFiles = $this->getUploadByUID($this->post->uid, $filesName, $labelsName);
- $addedFiles = $addedFiles + $uidFiles;
- }
- if(!isset($oldObject->{$filesName})) $oldObject->{$filesName} = array();
- $files = array_diff(array_keys($oldObject->{$filesName}), array_keys($deleteFiles));
- $files = array_merge($files, array_keys($addedFiles));
- $newObject->addedFiles = $addedFiles;
- $newObject->renameFiles = $renameFiles;
- $newObject->deleteFiles = $deleteFiles;
- $newObject->{$filesName} = implode(',', $files);
- }
- }
|