Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1051187
upload_helper.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Jul 3, 8:39 PM
Size
9 KB
Mime Type
text/x-php
Expires
Sat, Jul 5, 8:39 PM (20 h, 50 m)
Engine
blob
Format
Raw Data
Handle
679189
Attached To
rINP In-Portal
upload_helper.php
View Options
<?php
/**
* @version $Id: upload_helper.php 16395 2016-11-12 12:43:14Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2012 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
class
kUploadHelper
extends
kHelper
{
/**
* Creates kUploadHelper instance.
*/
public
function
__construct
()
{
parent
::
__construct
();
// 5 minutes execution time
@
set_time_limit
(
5
*
60
);
}
/**
* Handles the upload.
*
* @param kEvent $event Event.
*
* @return string
* @throws kUploaderException When upload could not be handled properly.
*/
public
function
handle
(
kEvent
$event
)
{
$this
->
disableBrowserCache
();
// Uncomment this one to fake upload time
// sleep(5);
if
(
!
$this
->
Application
->
HttpQuery
->
Post
)
{
// Variables {field, id, flashsid} are always submitted through POST!
// When file size is larger, then "upload_max_filesize" (in php.ini),
// then these variables also are not submitted.
throw
new
kUploaderException
(
'File size exceeds allowed limit.'
,
413
);
}
if
(
!
$this
->
checkPermissions
(
$event
)
)
{
// 403 Forbidden
throw
new
kUploaderException
(
'You don
\'
t have permissions to upload.'
,
403
);
}
$value
=
$this
->
Application
->
GetVar
(
'file'
);
if
(
!
$value
||
(
$value
[
'error'
]
!=
UPLOAD_ERR_OK
)
)
{
// 413 Request Entity Too Large (file uploads disabled OR uploaded file was
// too large for web server to accept, see "upload_max_filesize" in php.ini)
throw
new
kUploaderException
(
'File size exceeds allowed limit.'
,
413
);
}
$value
=
$this
->
Application
->
unescapeRequestVariable
(
$value
);
$tmp_path
=
WRITEABLE
.
'/tmp/'
;
$filename
=
$this
->
getUploadedFilename
()
.
'.tmp'
;
$id
=
$this
->
Application
->
GetVar
(
'id'
);
if
(
$id
)
{
$filename
=
$id
.
'_'
.
$filename
;
}
if
(
!
is_writable
(
$tmp_path
)
)
{
// 500 Internal Server Error
// check both temp and live upload directory
throw
new
kUploaderException
(
'Write permissions not set on the server, please contact server administrator.'
,
500
);
}
/** @var FileHelper $file_helper */
$file_helper
=
$this
->
Application
->
recallObject
(
'FileHelper'
);
$filename
=
$file_helper
->
ensureUniqueFilename
(
$tmp_path
,
$filename
);
$storage_format
=
$this
->
getStorageFormat
(
$this
->
Application
->
GetVar
(
'field'
),
$event
);
if
(
$storage_format
)
{
$image_helper
=
$this
->
Application
->
recallObject
(
'ImageHelper'
);
/* @var $image_helper ImageHelper */
$this
->
moveUploadedFile
(
$value
[
'tmp_name'
]
.
'.jpg'
);
// add extension, so ResizeImage can work
$url
=
$image_helper
->
ResizeImage
(
$value
[
'tmp_name'
]
.
'.jpg'
,
$storage_format
);
$tmp_name
=
preg_replace
(
'/^'
.
preg_quote
(
$this
->
Application
->
BaseURL
(),
'/'
)
.
'/'
,
'/'
,
$url
);
rename
(
$tmp_name
,
$tmp_path
.
$filename
);
}
else
{
$this
->
moveUploadedFile
(
$tmp_path
.
$filename
);
}
$this
->
deleteTempFiles
(
$tmp_path
);
$thumbs_path
=
preg_replace
(
'/^'
.
preg_quote
(
FULL_PATH
,
'/'
)
.
'/'
,
''
,
$tmp_path
,
1
);
$thumbs_path
=
FULL_PATH
.
THUMBS_PATH
.
$thumbs_path
;
if
(
file_exists
(
$thumbs_path
)
)
{
$this
->
deleteTempFiles
(
$thumbs_path
);
}
return
preg_replace
(
'/^'
.
preg_quote
(
$id
,
'/'
)
.
'_/'
,
''
,
$filename
);
}
/**
* Sends headers to ensure, that response is never cached.
*
* @return void
*/
protected
function
disableBrowserCache
()
{
header
(
'Expires: Mon, 26 Jul 1997 05:00:00 GMT'
);
header
(
'Last-Modified: '
.
gmdate
(
'D, d M Y H:i:s'
)
.
' GMT'
);
header
(
'Cache-Control: no-store, no-cache, must-revalidate'
);
header
(
'Cache-Control: post-check=0, pre-check=0'
,
false
);
header
(
'Pragma: no-cache'
);
}
/**
* Checks, that flash uploader is allowed to perform upload
*
* @param kEvent $event
* @return bool
*/
protected
function
checkPermissions
(
kEvent
$event
)
{
// Flash uploader does NOT send correct cookies, so we need to make our own check
$cookie_name
=
'adm_'
.
$this
->
Application
->
ConfigValue
(
'SessionCookieName'
);
$this
->
Application
->
HttpQuery
->
Cookie
[
'cookies_on'
]
=
1
;
$this
->
Application
->
HttpQuery
->
Cookie
[
$cookie_name
]
=
$this
->
Application
->
GetVar
(
'flashsid'
);
// this prevents session from auto-expiring when KeepSessionOnBrowserClose & FireFox is used
$this
->
Application
->
HttpQuery
->
Cookie
[
$cookie_name
.
'_live'
]
=
$this
->
Application
->
GetVar
(
'flashsid'
);
$admin_session
=
$this
->
Application
->
recallObject
(
'Session.admin'
);
/* @var $admin_session Session */
if
(
$admin_session
->
RecallVar
(
'user_id'
)
==
USER_ROOT
)
{
return
true
;
}
// copy some data from given session to current session
$backup_user_id
=
$this
->
Application
->
RecallVar
(
'user_id'
);
$this
->
Application
->
StoreVar
(
'user_id'
,
$admin_session
->
RecallVar
(
'user_id'
));
$backup_user_groups
=
$this
->
Application
->
RecallVar
(
'UserGroups'
);
$this
->
Application
->
StoreVar
(
'UserGroups'
,
$admin_session
->
RecallVar
(
'UserGroups'
));
// check permissions using event, that have "add|edit" rule
$check_event
=
new
kEvent
(
$event
->
getPrefixSpecial
()
.
':OnProcessSelected'
);
$check_event
->
setEventParam
(
'top_prefix'
,
$this
->
Application
->
GetTopmostPrefix
(
$event
->
Prefix
,
true
));
/** @var kEventHandler $event_handler */
$event_handler
=
$this
->
Application
->
recallObject
(
$event
->
Prefix
.
'_EventHandler'
);
$allowed_to_upload
=
$event_handler
->
CheckPermission
(
$check_event
);
// restore changed data, so nothing gets saved to database
$this
->
Application
->
StoreVar
(
'user_id'
,
$backup_user_id
);
$this
->
Application
->
StoreVar
(
'UserGroups'
,
$backup_user_groups
);
return
$allowed_to_upload
;
}
/**
* Returns uploaded filename.
*
* @return string
*/
protected
function
getUploadedFilename
()
{
if
(
isset
(
$_REQUEST
[
'name'
])
)
{
$file_name
=
$_REQUEST
[
'name'
];
}
elseif
(
!
empty
(
$_FILES
)
)
{
$file_name
=
$_FILES
[
'file'
][
'name'
];
}
else
{
$file_name
=
uniqid
(
'file_'
);
}
return
$file_name
;
}
/**
* Gets storage format for a given field.
*
* @param string $field_name
* @param kEvent $event
* @return bool
*/
protected
function
getStorageFormat
(
$field_name
,
kEvent
$event
)
{
$config
=
$event
->
getUnitConfig
();
$field_options
=
$config
->
getFieldByName
(
$field_name
);
if
(
!
$field_options
)
{
$field_options
=
$config
->
getVirtualFieldByName
(
$field_name
);
}
return
isset
(
$field_options
[
'storage_format'
])
?
$field_options
[
'storage_format'
]
:
false
;
}
/**
* Moves uploaded file to given location.
*
* @param string $file_path File path.
*
* @return void
* @throws kUploaderException When upload could not be handled properly.
*/
protected
function
moveUploadedFile
(
$file_path
)
{
// Chunking might be enabled
$chunk
=
(
int
)
$this
->
Application
->
GetVar
(
'chunk'
,
0
);
$chunks
=
(
int
)
$this
->
Application
->
GetVar
(
'chunks'
,
0
);
// Open temp file
if
(
!
$out
=
@
fopen
(
"{$file_path}.part"
,
$chunks
?
'ab'
:
'wb'
)
)
{
throw
new
kUploaderException
(
'Failed to open output stream.'
,
102
);
}
if
(
!
empty
(
$_FILES
)
)
{
if
(
$_FILES
[
'file'
][
'error'
]
||
!
is_uploaded_file
(
$_FILES
[
'file'
][
'tmp_name'
])
)
{
throw
new
kUploaderException
(
'Failed to move uploaded file.'
,
103
);
}
// Read binary input stream and append it to temp file
if
(
!
$in
=
@
fopen
(
$_FILES
[
'file'
][
'tmp_name'
],
'rb'
)
)
{
throw
new
kUploaderException
(
'Failed to open input stream.'
,
101
);
}
}
else
{
if
(
!
$in
=
@
fopen
(
'php://input'
,
'rb'
)
)
{
throw
new
kUploaderException
(
'Failed to open input stream.'
,
101
);
}
}
while
(
$buff
=
fread
(
$in
,
4096
)
)
{
fwrite
(
$out
,
$buff
);
}
@
fclose
(
$out
);
@
fclose
(
$in
);
// Check if file has been uploaded
if
(
!
$chunks
||
$chunk
==
$chunks
-
1
)
{
// Strip the temp .part suffix off
rename
(
"{$file_path}.part"
,
$file_path
);
}
}
/**
* Delete temporary files, that won't be used for sure
*
* @param string $path
* @return void
*/
protected
function
deleteTempFiles
(
$path
)
{
$files
=
glob
(
$path
.
'*.*'
);
$max_file_date
=
strtotime
(
'-1 day'
);
foreach
(
$files
as
$file
)
{
if
(
filemtime
(
$file
)
<
$max_file_date
)
{
unlink
(
$file
);
}
}
}
/**
* Prepares object for operations with file on given field.
*
* @param kEvent $event Event.
* @param string $field Field.
*
* @return kDBItem
*/
public
function
prepareUploadedFile
(
kEvent
$event
,
$field
)
{
$object
=
$event
->
getObject
(
Array
(
'skip_autoload'
=>
true
));
/* @var $object kDBItem */
$filename
=
$this
->
getSafeFilename
();
if
(
!
$filename
)
{
$object
->
SetDBField
(
$field
,
''
);
return
$object
;
}
// set current uploaded file
if
(
$this
->
Application
->
GetVar
(
'tmp'
)
)
{
$options
=
$object
->
GetFieldOptions
(
$field
);
$options
[
'upload_dir'
]
=
WRITEBALE_BASE
.
'/tmp/'
;
unset
(
$options
[
'include_path'
]);
$object
->
SetFieldOptions
(
$field
,
$options
);
$filename
=
$this
->
Application
->
GetVar
(
'id'
)
.
'_'
.
$filename
;
}
$object
->
SetDBField
(
$field
,
$filename
);
return
$object
;
}
/**
* Returns safe version of filename specified in url
*
* @return bool|string
* @access protected
*/
protected
function
getSafeFilename
()
{
$filename
=
$this
->
Application
->
GetVar
(
'file'
);
$filename
=
$this
->
Application
->
unescapeRequestVariable
(
$filename
);
if
(
(
strpos
(
$filename
,
'../'
)
!==
false
)
||
(
trim
(
$filename
)
!==
$filename
)
)
{
// when relative paths or special chars are found template names from url, then it's hacking attempt
return
false
;
}
return
$filename
;
}
}
class
kUploaderException
extends
Exception
{
}
Event Timeline
Log In to Comment