7 class File extends \Rsi\Fred\Controller\Widget{
40 $config = array_merge(parent::clientConfig(),$this->
get([self::TYPES]));
41 if(!$this->max) $config[self::MAX] = \Rsi\Number::shorthandBytes(ini_get(
'post_max_size'));
42 if($this->trailer === null) $config[self::TRAILER] =
'%n (%s %u)';
44 $config[self::FILENAME] = \Rsi\File::basename($this->filename);
45 $config[
'fileExists'] = is_file($this->filename);
46 if($this->sideloadControllerName && $this->sideloadPath && !$this->_controller->component(
'client')->mobile){
48 foreach($this->types as $type)
if($image = preg_match(
'/^(image|jpe?g)/i',$type))
break;
52 if($this->userFiles && $this->_controller->component(
'user')->id) $config[self::USER_FILES] =
true;
54 if($this->multi) $config[self::MULTI] =
true;
63 if($value && is_array($value)) $value = $this->multi
64 ? array_column($this->_multiRaw = $value,
'tmp_name')
65 : \Rsi\Record::get($this->_raw = $value,
'tmp_name');
66 elseif(!$value && $this->filename && is_file($this->filename)) $value =
$this->filename;
67 return parent::purgeBase($value);
71 return $this->_controller->component(
'event')->trigger(self::EVENT_UPLOAD,$this,$name);
74 protected function checkMin($value,$index = null){
75 return parent::checkMin(filesize($value));
78 protected function checkMax($value,$index = null){
79 return parent::checkMax(filesize($value));
83 return !$this->_raw || (is_uploaded_file($value) && !$this->_raw[
'error']);
87 if($this->_raw) $value = $this->_raw[
'name'];
88 if(!$this->types || in_array(\
Rsi\File::ext($value),$this->types))
return true;
89 $mime = \Rsi\File::mime($value);
90 foreach($this->types as $type)
91 if(preg_match(substr($type,0,1) ==
'/' ? $type :
'/^' . str_replace(
'*',
'.*',$type) .
'$/',$mime))
return true;
95 public function check($value,$index = null){
96 if(!$this->_multiRaw) $error = parent::check($value,$index);
97 else foreach($this->_multiRaw as $this->_raw)
if($error = parent::check($this->_raw[
'tmp_name'],$index))
break;
98 if(!$error && $value && !is_array($value) && $this->filename && $this->_raw){
99 if(!move_uploaded_file($value,$this->filename))
100 throw new \Exception(
"Can not move uploaded file from '$value' to '{$this->filename}'");
101 else $error = $this->
uploadEvent($this->_raw[
'name']);
114 $count = $rotate =
false;
117 $image = imagecreatefromstring(file_get_contents(
$filename));
118 $factor = min($this->previewSize / ($width = imagesx($image)),$this->previewSize / ($height = imagesy($image)));
119 $scaled = imagescale($image,round($factor * $width),round($factor * $height));
120 imagedestroy($image);
123 $preview[] = ob_get_clean();
124 imagedestroy($scaled);
125 $rotate = in_array(\
Rsi\File::ext(
$filename),[
'gif',
'jpg',
'jpeg',
'png']);
128 $this->log->info($e);
129 $temp = \Rsi\File::tempFile(
'png');
130 if(class_exists(
'Imagick'))
try{
132 $count = $image->getNumberImages();
133 foreach($image as $index => $page){
134 $page->setImageBackgroundColor(
'white');
135 $page->setImageFormat(
'png');
136 $page->thumbnailImage($this->previewSize,0);
137 $page->writeImage($temp);
138 $preview[] = file_get_contents($temp);
139 if(++$index >= $this->previewMax)
break;
144 $this->log->info($e);
147 \Rsi\File::unlink($temp);
150 extract($this->services->preview(
$filename,$this->previewSize,$this->previewMax));
153 $this->log->info($e);
156 if(!$count) $count = count($preview);
184 if($angle > 0) $image = imagerotate($image,-$angle,imagecolorallocate($image,255,255,255));
186 case -1: imageflip($image,IMG_FLIP_HORIZONTAL);
break;
187 case -2: imageflip($image,IMG_FLIP_VERTICAL);
break;
189 $result = call_user_func(
'image' . $ext,$image,
$filename);
190 imagedestroy($image);
194 $this->log->info($e);
205 $temp = \Rsi\File::tempFile(\
Rsi\File::ext($this->filename),$data);
206 if($error = $this->
check($temp)) \Rsi\File::unlink($temp);
207 elseif(!rename($temp,$this->filename))
throw new \Exception(
"Could not rename('$temp','{$this->filename}')");
210 foreach($this->
preview(null,$count,$rotate) as $image) $preview[] = base64_encode($image);
211 $this->request->result = compact(
'error',
'name',
'preview',
'count',
'rotate') + [
'size' => strlen($data),
'fileExists' => is_file($this->filename)];
214 \Rsi\File::unlink($temp);
224 return $this->sideloadPath . $token . ($index === null ?
'' :
'-' . $index) . $this->sideloadExt;
232 return \Rsi\Http::host(
true) . $this->_controller->component(
'router')->reverse($this->sideloadControllerName,null,compact(
'token'));
238 if($this->sideloadPath && !rand(0,$this->sideloadGarbageChance))
try{
239 foreach((
new \GlobIterator($this->sideloadPath .
'*' . $this->sideloadExt)) as
$filename => $file)
241 $session = $this->_controller->session;
242 if($tokens = $session->sideloadTokens){
243 foreach($tokens as $token => $time)
if(!is_file($this->
sideloadFilename($token))) unset($tokens[$token]);
244 $session->sideloadTokens = $tokens;
248 $this->log->error($e);
253 if($this->_display >= self::DISPLAY_WRITEABLE){
254 session_write_close();
255 $this->
rotate((
int)$this->request->angle);
257 foreach($this->
preview(null,$count,$rotate) as $image) $preview[] = base64_encode($image);
258 clearstatcache(
false,$this->filename);
259 $this->request->result = compact(
'preview',
'count',
'rotate') + [
'size' => filesize($this->filename)];
264 if(($this->_display >= self::DISPLAY_READABLE) && $this->filename && is_file($this->filename)){
265 \Rsi\Http::downloadHeaders($this->filename,null,filesize($this->filename));
266 readfile($this->filename);
273 ($this->_display >= self::DISPLAY_WRITEABLE) &&
275 ($value = \
Rsi\Record::get($this->request->file(
'data'),
'tmp_name'))
276 ) $this->
processUpload(file_get_contents($value),$this->request->name);
280 if(($this->_display >= self::DISPLAY_WRITEABLE) && !$this->required && $this->filename)
281 $this->request->result = [
'deleted' => \Rsi\File::unlink($this->filename)];
285 if(($this->_display >= self::DISPLAY_WRITEABLE) && $this->userFiles) $this->request->result = [
286 'files' => $this->_controller->component(
'user')->files->list($this->types),
287 'preview' => (bool)$this->previewSize
292 if($data = $this->_controller->component(
'user')->files->fetch($this->request->name)){
293 session_write_close();
294 $temp = \Rsi\File::tempFile(
'tmp',$data);
296 foreach($this->
preview($temp) as $image) $preview[] = base64_encode($image);
298 $this->request->result = $preview;
303 if(($this->_display >= self::DISPLAY_WRITEABLE) && $this->filename && $this->userFiles){
304 $data = $this->_controller->component(
'user')->files->fetch(
$filename = $this->request->name);
310 if(($this->_display >= self::DISPLAY_WRITEABLE) && $this->filename && $this->sideloadPath && $this->sideloadControllerName){
313 \Rsi\File::serialize(
317 'config' => array_merge($this->_config,[self::FILENAME => null]),
318 'time' => $time = time()
322 $session = $this->_controller->session;
323 $tokens = $session->sideloadTokens ?: [];
324 $tokens[$token] = $time;
325 $session->sideloadTokens = $tokens;
327 $this->request->result = [
331 'hint' => $this->trans->str($this->sideloadHint,compact(
'token',
'url'))
337 if($token = $this->sideloadToken){
338 header(
'Content-Type: image/png');
339 imagepng((
new Qr(Qr::ECC_MEDIUM,null,10))->dataImage($this->
sideloadUrl($token)));
348 while($skip++ < $this->sideloadSkip)
355 $this->log->warning(
'Error while processig sideload file: ' . $e->getMessage(),__FILE__,__LINE__);
363 $session = $this->_controller->session;
365 ($tokens = $session->sideloadTokens) &&
366 array_key_exists($token = $this->request->token,$tokens) &&
367 ($tokens[$token] > ($time = time()) - 2 * $this->sideloadInterval)
369 $tokens[$token] = $time;
370 $session->sideloadTokens = $tokens;