liteFM fixes
This commit is contained in:
parent
b9727fdfa7
commit
751874ea8c
5 changed files with 280 additions and 84 deletions
|
|
@ -234,7 +234,7 @@ function downloadFile(home_id, file_id, file_size, file_name)
|
|||
function getFilePart()
|
||||
{
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', "home.php?m=litefm&home_id="+home_id+"&item="+file_id+"&name="+file_name+"&p=get&type=cleared&size="+file_size+"&did="+did, true);
|
||||
xhr.open('POST', "home.php?m=litefm&home_id="+home_id+"&item="+file_id+"&name="+encodeURIComponent(file_name)+"&p=get&type=cleared&size="+file_size+"&did="+did, true);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onload = function(e) {
|
||||
if(this.response.byteLength != 0)
|
||||
|
|
@ -283,6 +283,15 @@ function downloadFile(home_id, file_id, file_size, file_name)
|
|||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
function escapeHtml(value) {
|
||||
return String(value)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
/* translation & info */
|
||||
var select_at_least_one_item = $('#dialog').attr('data-select_at_least_one_item'),
|
||||
ask_delete = $('#dialog').attr('data-ask_delete'),
|
||||
|
|
@ -389,7 +398,7 @@ $(document).ready(function(){
|
|||
item = $(this).attr('data-item');
|
||||
value = $(this).attr('value');
|
||||
addpost.items.push(item);
|
||||
items += "<br>"+value;
|
||||
items += "<br>"+escapeHtml(value);
|
||||
});
|
||||
if(items != '')
|
||||
{
|
||||
|
|
@ -434,9 +443,9 @@ $(document).ready(function(){
|
|||
var items = '';
|
||||
$('input[class="item"]:checked').each(function(){
|
||||
item = $(this).attr('data-item');
|
||||
value = $(this).attr('value').replace('"', """);
|
||||
value = $(this).attr('value');
|
||||
addpost.items.push(item);
|
||||
items += "<br><input class='rename' type=text style='width:100%;' name='"+item+"' value=\""+value+"\">";
|
||||
items += "<br><input class='rename' type=text style='width:100%;' name='"+item+"' value=\""+escapeHtml(value)+"\">";
|
||||
});
|
||||
if(items != '')
|
||||
{
|
||||
|
|
@ -487,7 +496,7 @@ $(document).ready(function(){
|
|||
item = $(this).attr('data-item');
|
||||
value = $(this).attr('value');
|
||||
addpost.items.push(item);
|
||||
items += "<br>"+value;
|
||||
items += "<br>"+escapeHtml(value);
|
||||
});
|
||||
if(items != '')
|
||||
{
|
||||
|
|
@ -550,7 +559,7 @@ $(document).ready(function(){
|
|||
item = $(this).attr('data-item');
|
||||
value = $(this).attr('value');
|
||||
addpost.items.push(item);
|
||||
items += "<br>"+value;
|
||||
items += "<br>"+escapeHtml(value);
|
||||
});
|
||||
if(items != '')
|
||||
{
|
||||
|
|
@ -611,7 +620,7 @@ $(document).ready(function(){
|
|||
item = $(this).attr('data-item');
|
||||
value = $(this).attr('value');
|
||||
addpost.items.push(item);
|
||||
items += "<br>"+value;
|
||||
items += "<br>"+escapeHtml(value);
|
||||
});
|
||||
if(items != '')
|
||||
{
|
||||
|
|
@ -675,7 +684,7 @@ $(document).ready(function(){
|
|||
if(ext.match(/^(tar|tgz|gz|Z|zip|bz2|tbz|lzma|xz|txz)$/i) != null)
|
||||
{
|
||||
addpost.items.push(item);
|
||||
items += "<br>"+value;
|
||||
items += "<br>"+escapeHtml(value);
|
||||
}
|
||||
});
|
||||
if(items != '')
|
||||
|
|
@ -902,7 +911,7 @@ $(document).ready(function(){
|
|||
}
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: 'home.php?m=litefm&home_id='+home_id+'&type=cleared&pid='+file['pid']+'&size='+file['size']+'&filename='+file['filename']+"&data_type=json",
|
||||
url: 'home.php?m=litefm&home_id='+home_id+'&type=cleared&pid='+file['pid']+'&size='+file['size']+'&filename='+encodeURIComponent(file['filename'])+"&data_type=json",
|
||||
dataType:'json',
|
||||
async: false,
|
||||
success: function(data){
|
||||
|
|
@ -978,7 +987,7 @@ $(document).ready(function(){
|
|||
addpost.set_attr = $(this).attr('data-set_attr'),
|
||||
addpost.file_name = $(this).attr('data-file_name');
|
||||
addpost.item = $(this).attr('data-item');
|
||||
$('#dialog').html(ask_change_attr.replace("%file_name%",addpost.file_name));
|
||||
$('#dialog').html(ask_change_attr.replace("%file_name%",escapeHtml(addpost.file_name)));
|
||||
$('#dialog').dialog({
|
||||
autoOpen: true,
|
||||
width: 450,
|
||||
|
|
@ -1016,7 +1025,7 @@ $(document).ready(function(){
|
|||
item = $(this).attr('data-item');
|
||||
value = $(this).attr('value');
|
||||
addpost.items.push(item);
|
||||
items += "<br>"+value;
|
||||
items += "<br>"+escapeHtml(value);
|
||||
});
|
||||
if(items != '')
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ if(preg_match("/t/",$server_home['access_rights']) > 0)
|
|||
{
|
||||
$module_buttons = array();
|
||||
|
||||
// WE DONT WANT A FTP BUTTON, BUT WE DO NEED THE FTP FUNCTIONALITY, SO WE WILL NOT ADD A FTP BUTTON TO THE GAME MONITOR, BUT WE WILL STILL ALLOW THE USER TO ACCESS THE FTP MODULE FOR THIS HOME
|
||||
return;
|
||||
|
||||
|
||||
$module_buttons = array(
|
||||
"<a class='monitorbutton' href='?m=ftp&home_id=".$server_home['home_id']."'>
|
||||
|
|
|
|||
|
|
@ -68,31 +68,30 @@ function exec_ogp_module()
|
|||
if (!isset($_SESSION[$cwd_session_key]) || !is_string($_SESSION[$cwd_session_key])) {
|
||||
$_SESSION[$cwd_session_key] = '';
|
||||
}
|
||||
$path = clean_path($home_cfg['home_path']."/".$_SESSION[$cwd_session_key]);
|
||||
$path = litefm_safe_join_home_path($home_cfg['home_path'], $_SESSION[$cwd_session_key]);
|
||||
if ($path === false)
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
echo "<table class='center'><tr><td><a href='?m=gamemanager&p=game_monitor&home_id=".$home_cfg['home_id']."'><< ".get_lang('back')."</a></td></tr></table>";
|
||||
return;
|
||||
}
|
||||
|
||||
$home_root = clean_path($home_cfg['home_path']);
|
||||
if (!$remote->rfile_exists($home_root))
|
||||
{
|
||||
print_failure("Server files have not been installed yet.");
|
||||
echo "<table class='center'><tr><td><a href='?m=gamemanager&p=game_monitor&home_id=".$home_cfg['home_id']."'><< ".get_lang('back')."</a></td></tr></table>";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$remote->rfile_exists($path))
|
||||
{
|
||||
while(!$remote->rfile_exists($path))
|
||||
{
|
||||
$current_cwd = isset($_SESSION[$cwd_session_key]) ? (string)$_SESSION[$cwd_session_key] : '';
|
||||
if ($current_cwd === '' || $current_cwd === '.' || $current_cwd === DIRECTORY_SEPARATOR) {
|
||||
print_failure("Server files have not been installed yet.");
|
||||
$requested_rel_path = isset($_SESSION[$cwd_session_key]) ? trim((string)$_SESSION[$cwd_session_key], '/') : '';
|
||||
$requested_rel_path = $requested_rel_path === '' ? '/' : $requested_rel_path;
|
||||
print_failure("Directory not found: " . litefm_escape_html($requested_rel_path));
|
||||
echo "<table class='center'><tr><td><a href='?m=gamemanager&p=game_monitor&home_id=".$home_cfg['home_id']."'><< ".get_lang('back')."</a></td></tr></table>";
|
||||
return;
|
||||
}
|
||||
$parent_cwd = dirname($current_cwd);
|
||||
if (!is_string($parent_cwd) || $parent_cwd === '.' || $parent_cwd === DIRECTORY_SEPARATOR) {
|
||||
$parent_cwd = '';
|
||||
}
|
||||
$_SESSION[$cwd_session_key] = $parent_cwd;
|
||||
$path = clean_path($home_cfg['home_path']."/".$_SESSION[$cwd_session_key]);
|
||||
if($path == clean_path($home_cfg['home_path']."/"))
|
||||
{
|
||||
print_failure("Server files have not been installed yet.");
|
||||
echo "<table class='center'><tr><td><a href='?m=gamemanager&p=game_monitor&home_id=".$home_cfg['home_id']."'><< ".get_lang('back')."</a></td></tr></table>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get File Operations Keys
|
||||
$fo_keys = get_file_operations_keys();
|
||||
|
|
@ -112,7 +111,12 @@ function exec_ogp_module()
|
|||
{
|
||||
$bytes = $_GET['size'];
|
||||
$totalsize = $bytes / 1024;
|
||||
$filename = $_GET['filename'];
|
||||
$filename = litefm_decode_name_param($_GET['filename']);
|
||||
if (!litefm_is_valid_path_component($filename))
|
||||
{
|
||||
echo json_encode(array('pct' => 0, 'complete' => false));
|
||||
return;
|
||||
}
|
||||
$kbytes = $remote->rsync_progress( clean_path( $path."/".$filename ) );
|
||||
list($totalsize,$mbytes,$pct) = explode(";",do_progress($kbytes,$totalsize));
|
||||
$totalmbytes = round($totalsize / 1024, 2);
|
||||
|
|
@ -177,10 +181,9 @@ function exec_ogp_module()
|
|||
// if file not uploaded then skip it
|
||||
if ( !is_uploaded_file($_FILES['files']['tmp_name'][$i]) )
|
||||
continue;
|
||||
// now we can move uploaded files
|
||||
$bad_chars = preg_replace( "/([[:alnum:]_\.-]*)/", "", $_FILES['files']['name'][$i] );
|
||||
$bad_arr = str_split( $bad_chars );
|
||||
$filename = str_replace( $bad_arr, "", $_FILES['files']['name'][$i] );
|
||||
$filename = basename((string)$_FILES['files']['name'][$i]);
|
||||
if (!litefm_is_valid_path_component($filename))
|
||||
continue;
|
||||
$dest_file_path = clean_path( $upload_folder_path . "/" . $filename . ".txt" );
|
||||
$file_url = str_replace( "home.php", $dest_file_path, $url );
|
||||
if( file_exists( $dest_file_path ) )
|
||||
|
|
@ -205,7 +208,17 @@ function exec_ogp_module()
|
|||
elseif( isset( $_POST['create_folder'] ) and $fo['create_folder'] == "1" )
|
||||
{
|
||||
$folder_name = stripslashes($_POST['folder_name']);
|
||||
if (!litefm_is_valid_path_component($folder_name))
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
return;
|
||||
}
|
||||
$folder_path = clean_path( $path . "/" . $folder_name );
|
||||
if (!litefm_path_within_home($home_cfg['home_path'], $folder_path))
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
return;
|
||||
}
|
||||
$remote->shell_action('create_dir', $folder_path);
|
||||
$db->logger( get_lang("create_folder") . ": " . $folder_path );
|
||||
}
|
||||
|
|
@ -242,8 +255,18 @@ function exec_ogp_module()
|
|||
if(isset($_SESSION['fm_files_'.$home_id][$item]))
|
||||
{
|
||||
$item_path = clean_path( $path . "/" . $_SESSION['fm_files_'.$home_id][$item] );
|
||||
$new_item = removeInvalidFileNameCharacters(stripslashes($_POST['values'][$i]));
|
||||
$new_item = stripslashes($_POST['values'][$i]);
|
||||
if (!litefm_is_valid_path_component($new_item))
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
continue;
|
||||
}
|
||||
$new_item_path = clean_path( $path . "/" . $new_item );
|
||||
if (!litefm_path_within_home($home_cfg['home_path'], $new_item_path))
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
continue;
|
||||
}
|
||||
if ($item_path != $new_item_path)
|
||||
{
|
||||
$remote->shell_action('rename', "$item_path;$new_item_path");
|
||||
|
|
@ -256,8 +279,18 @@ function exec_ogp_module()
|
|||
// Move Files/Folders
|
||||
elseif( isset( $_POST['move'] ) and $fo['move'] == "1" )
|
||||
{
|
||||
$selected_path = preg_replace("#[/\.\./]+#","/", stripslashes($_POST['selected_path']));
|
||||
$destination = clean_path($home_cfg['home_path']. "/" . $selected_path);
|
||||
$selected_path = litefm_normalize_relative_path(stripslashes($_POST['selected_path']));
|
||||
if ($selected_path === false)
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
return;
|
||||
}
|
||||
$destination = litefm_safe_join_home_path($home_cfg['home_path'], $selected_path);
|
||||
if ($destination === false)
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
return;
|
||||
}
|
||||
if($path != $destination)
|
||||
{
|
||||
if($remote->rfile_exists($destination))
|
||||
|
|
@ -278,8 +311,18 @@ function exec_ogp_module()
|
|||
// Copy Files/Folders
|
||||
elseif( isset( $_POST['copy'] ) and $fo['copy'] == "1" )
|
||||
{
|
||||
$selected_path = preg_replace("#[/\.\./]+#","/", stripslashes($_POST['selected_path']));
|
||||
$destination = clean_path($home_cfg['home_path']. "/" . $selected_path);
|
||||
$selected_path = litefm_normalize_relative_path(stripslashes($_POST['selected_path']));
|
||||
if ($selected_path === false)
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
return;
|
||||
}
|
||||
$destination = litefm_safe_join_home_path($home_cfg['home_path'], $selected_path);
|
||||
if ($destination === false)
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
return;
|
||||
}
|
||||
if($path != $destination)
|
||||
{
|
||||
if($remote->rfile_exists($destination))
|
||||
|
|
@ -320,8 +363,18 @@ function exec_ogp_module()
|
|||
// uncompress
|
||||
elseif( isset( $_POST['uncompress'] ) and $fo['uncompress'] == "1" )
|
||||
{
|
||||
$selected_path = preg_replace("#[/\.\./]+#","/", stripslashes($_POST['selected_path']));
|
||||
$destination = clean_path($home_cfg['home_path']. "/" . $selected_path);
|
||||
$selected_path = litefm_normalize_relative_path(stripslashes($_POST['selected_path']));
|
||||
if ($selected_path === false)
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
return;
|
||||
}
|
||||
$destination = litefm_safe_join_home_path($home_cfg['home_path'], $selected_path);
|
||||
if ($destination === false)
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
return;
|
||||
}
|
||||
if($remote->rfile_exists($destination))
|
||||
{
|
||||
foreach ((array)$_POST['items'] as $item)
|
||||
|
|
@ -338,8 +391,20 @@ function exec_ogp_module()
|
|||
// Create file
|
||||
elseif( isset( $_POST['create_file'] ) and $fo['create_file'] == "1" )
|
||||
{
|
||||
$file_name = removeInvalidFileNameCharacters(stripslashes($_POST['file_name']));
|
||||
$file_name = stripslashes($_POST['file_name']);
|
||||
if (!litefm_is_valid_path_component($file_name))
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
$file_name = "";
|
||||
}
|
||||
if ($file_name === "")
|
||||
return;
|
||||
$destination = clean_path( $path . "/" . $file_name);
|
||||
if (!litefm_path_within_home($home_cfg['home_path'], $destination))
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
return;
|
||||
}
|
||||
$remote->shell_action('touch', $destination);
|
||||
$db->logger( get_lang("create_file") . ": $destination" );
|
||||
}
|
||||
|
|
@ -437,7 +502,12 @@ function exec_ogp_module()
|
|||
|
||||
if (!is_array($dirlist))
|
||||
{
|
||||
if(isset($_SESSION['fm_cwd_'.$home_id]))
|
||||
if ($remote->rfile_exists($path))
|
||||
{
|
||||
print_failure("Directory exists but cannot be opened. Check permissions.");
|
||||
return;
|
||||
}
|
||||
elseif(isset($_SESSION['fm_cwd_'.$home_id]))
|
||||
{
|
||||
unset($_SESSION['fm_cwd_'.$home_id]);
|
||||
$view->refresh("?m=litefm&home_id=$home_id",0);
|
||||
|
|
@ -475,21 +545,25 @@ function exec_ogp_module()
|
|||
$dirlist['directorys'] = array_orderby($dirlist['directorys'], 'filename', SORT_ASC);
|
||||
foreach ((array)$dirlist['directorys'] as $directory)
|
||||
{
|
||||
$directory['filename'] = removeInvalidFileNameCharacters($directory['filename']);
|
||||
$directoryName = $directory['filename'];
|
||||
if (!litefm_is_valid_path_component($directoryName))
|
||||
continue;
|
||||
$encodedDirectoryName = rawurlencode($directoryName);
|
||||
$escapedDirectoryName = litefm_escape_html($directoryName);
|
||||
|
||||
echo "<tr>\n".
|
||||
"<td>".
|
||||
"<input type=checkbox name='folder' data-item='$i' value=\"" . str_replace('"', """, $directory['filename']) . "\" class='item' />\n".
|
||||
"<input type=checkbox name='folder' data-item='$i' value=\"" . $escapedDirectoryName . "\" class='item' />\n".
|
||||
"</td>".
|
||||
"<td align=left>".
|
||||
"<img class=\"viewitem\" src=\"" . check_theme_image("images/folder.png") . "\" alt=\"Directory\" /> ".
|
||||
"<a href=\"?m=litefm&home_id=$home_id&item=$i&name=" . urlencode($directory['filename']) . "&type=directory\">".
|
||||
$directory['filename'] . "</a></td>";
|
||||
"<a href=\"?m=litefm&home_id=$home_id&item=$i&name=" . $encodedDirectoryName . "&type=directory\">".
|
||||
$escapedDirectoryName . "</a></td>";
|
||||
if( $os == "linux" )
|
||||
echo "<td>-</td>";
|
||||
echo "<td>-</td> <td>" . $directory['user'] . " " . $directory['group']. "</td>\n".
|
||||
"</tr>\n";
|
||||
$_SESSION['fm_files_'.$home_id][$i] = $directory['filename'];
|
||||
$_SESSION['fm_files_'.$home_id][$i] = $directoryName;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
|
@ -499,12 +573,16 @@ function exec_ogp_module()
|
|||
$dirlist['files'] = array_orderby($dirlist['files'], 'filename', SORT_ASC);
|
||||
foreach ((array)$dirlist['files'] as $file)
|
||||
{
|
||||
$file['filename'] = removeInvalidFileNameCharacters($file['filename']);
|
||||
$fileName = $file['filename'];
|
||||
if (!litefm_is_valid_path_component($fileName))
|
||||
continue;
|
||||
$encodedFileName = rawurlencode($fileName);
|
||||
$escapedFileName = litefm_escape_html($fileName);
|
||||
|
||||
if( $os == "linux" )
|
||||
{
|
||||
if($isAdmin){
|
||||
$secureFile = "<td><div data-item='$i' data-file_name=\"" . str_replace('"', """, $file['filename']) . "\" class='chattrButton ";
|
||||
$secureFile = "<td><div data-item='$i' data-file_name=\"" . litefm_escape_html($file['filename']) . "\" class='chattrButton ";
|
||||
if( preg_match( "/i/", $file['attr'] ) ){
|
||||
$secureFile .= "locked' data-set_attr='-i' ><i></i><span>". get_lang("chattr_no");
|
||||
}else{
|
||||
|
|
@ -526,15 +604,15 @@ function exec_ogp_module()
|
|||
|
||||
echo "<tr>\n".
|
||||
"<td>".
|
||||
"<input type=checkbox name='file' data-item='$i' value=\"" . str_replace('"', """, $file['filename']) . "\" class='item' />\n".
|
||||
"<input type=checkbox name='file' data-item='$i' value=\"" . $escapedFileName . "\" class='item' />\n".
|
||||
"</td>".
|
||||
"<td align=left id='fileid$i' >";
|
||||
echo "<img class=\"viewitem\" src=\"" . check_theme_image("images/txt.png") . "\" alt=\"Text file\" /> ".
|
||||
"<a href=\"?m=litefm&home_id=$home_id&item=$i&p=read_file&name=" . urlencode($file['filename']) . "&type=file\">". get_lang("button_edit") ."</a>".
|
||||
"<a href=\"javascript:downloadFile($home_id, $i, {$file['size']}, '".str_replace("'", "\'", $file['filename'])."');\" id=\"jsDwl$i\" >" .$file['filename'] . "</a> ".
|
||||
"<a href=\"?m=litefm&home_id=$home_id&item=$i&p=read_file&name=" . $encodedFileName . "&type=file\">". get_lang("button_edit") ."</a>".
|
||||
"<a href=\"javascript:downloadFile($home_id, $i, {$file['size']}, '".str_replace("'", "\\'", $fileName)."');\" id=\"jsDwl$i\" >" .$escapedFileName . "</a> ".
|
||||
"</td>$secureFile<td>" . $file['size'] . "</td> <td>" . $file['user'] . " " . $file['group']. "</td>\n";
|
||||
echo "</tr>\n";
|
||||
$_SESSION['fm_files_'.$home_id][$i] = $file['filename'];
|
||||
$_SESSION['fm_files_'.$home_id][$i] = $fileName;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
|
@ -544,12 +622,15 @@ function exec_ogp_module()
|
|||
$dirlist['binarys'] = array_orderby($dirlist['binarys'], 'filename', SORT_ASC);
|
||||
foreach ((array)$dirlist['binarys'] as $binary)
|
||||
{
|
||||
$binary['filename'] = removeInvalidFileNameCharacters($binary['filename']);
|
||||
$binaryName = $binary['filename'];
|
||||
if (!litefm_is_valid_path_component($binaryName))
|
||||
continue;
|
||||
$escapedBinaryName = litefm_escape_html($binaryName);
|
||||
|
||||
if( $os == "linux" )
|
||||
{
|
||||
if($isAdmin){
|
||||
$secureFile = "<td><div data-item='$i' data-file_name=\"" . str_replace('"', """, $binary['filename']) . "\" class='chattrButton ";
|
||||
$secureFile = "<td><div data-item='$i' data-file_name=\"" . litefm_escape_html($binary['filename']) . "\" class='chattrButton ";
|
||||
if( preg_match( "/i/", $binary['attr'] ) ){
|
||||
$secureFile .= "locked' data-set_attr='-i' ><i></i><span>". get_lang("chattr_no");
|
||||
}else{
|
||||
|
|
@ -571,14 +652,14 @@ function exec_ogp_module()
|
|||
|
||||
echo "<tr>\n".
|
||||
"<td>".
|
||||
"<input type=checkbox name='binary' data-item='$i' value=\"" . str_replace('"', """, $binary['filename']) . "\" class='item' />\n".
|
||||
"<input type=checkbox name='binary' data-item='$i' value=\"" . $escapedBinaryName . "\" class='item' />\n".
|
||||
"</td>".
|
||||
"<td align=left id='fileid$i' >";
|
||||
echo "<img class=\"viewitem\" src=\"" . check_theme_image("images/exec.png") . "\" alt=\"Binary file\" /> ".
|
||||
"<a href=\"javascript:downloadFile($home_id, $i, {$binary['size']}, '".str_replace("'", "\'", $binary['filename'])."');\" id=\"jsDwl$i\" >" .$binary['filename'] . "</a> ".
|
||||
"<a href=\"javascript:downloadFile($home_id, $i, {$binary['size']}, '".str_replace("'", "\\'", $binaryName)."');\" id=\"jsDwl$i\" >" .$escapedBinaryName . "</a> ".
|
||||
"</td>$secureFile<td>" . $binary['size'] . "</td><td>" . $binary['user'] . " " . $binary['group']. "</td>\n";
|
||||
echo "</tr>\n";
|
||||
$_SESSION['fm_files_'.$home_id][$i] = $binary['filename'];
|
||||
$_SESSION['fm_files_'.$home_id][$i] = $binaryName;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
|
@ -589,7 +670,7 @@ function exec_ogp_module()
|
|||
// Dialog translation && info
|
||||
$user = $db->getUserById($_SESSION['user_id']);
|
||||
echo "<div id='dialog' ".
|
||||
"data-folder=\"" . clean_path("/".str_replace('"', """, @$_SESSION['fm_cwd_'.$home_id])) . "\" " .
|
||||
"data-folder=\"" . litefm_escape_html(clean_path("/".(@$_SESSION['fm_cwd_'.$home_id] ?? ''))) . "\" " .
|
||||
"data-select_at_least_one_item='" . get_lang("select_at_least_one_item") . "' " .
|
||||
"data-ask_delete='" . get_lang("delete_item") . "' " .
|
||||
"data-ask_rename='" . get_lang("rename_item") . "' " .
|
||||
|
|
@ -615,7 +696,7 @@ function exec_ogp_module()
|
|||
"data-dest_email='" . get_lang("dest_email") . "' " .
|
||||
"data-user_email='" . $user['users_email'] . "' ";
|
||||
if($isAdmin)
|
||||
echo "data-ask_change_attr=\"" . get_lang_f( 'secure_item', clean_path( str_replace('"', """, $path) . "/%file_name%" ) ) . "\" ";
|
||||
echo "data-ask_change_attr=\"" . litefm_escape_html(get_lang_f( 'secure_item', clean_path( $path . "/%file_name%" ) )) . "\" ";
|
||||
echo "></div>";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,74 @@
|
|||
|
||||
require_once('includes/lib_remote.php');
|
||||
|
||||
function litefm_decode_name_param($value)
|
||||
{
|
||||
return rawurldecode((string)$value);
|
||||
}
|
||||
|
||||
function litefm_escape_html($value)
|
||||
{
|
||||
return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
function litefm_is_valid_path_component($name)
|
||||
{
|
||||
if (!is_string($name) || $name === '' || $name === '.' || $name === '..') {
|
||||
return false;
|
||||
}
|
||||
if (strpos($name, "\0") !== false || strpos($name, '/') !== false || strpos($name, '\\') !== false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function litefm_normalize_relative_path($relativePath)
|
||||
{
|
||||
$relativePath = str_replace('\\', '/', (string)$relativePath);
|
||||
$relativePath = preg_replace('#/+#', '/', $relativePath);
|
||||
$relativePath = trim($relativePath, '/');
|
||||
if ($relativePath === '') {
|
||||
return '';
|
||||
}
|
||||
if (strpos($relativePath, "\0") !== false) {
|
||||
return false;
|
||||
}
|
||||
if (preg_match('#(^|/)\.{1,2}(/|$)#', $relativePath)) {
|
||||
return false;
|
||||
}
|
||||
foreach (explode('/', $relativePath) as $segment) {
|
||||
if (!litefm_is_valid_path_component($segment)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $relativePath;
|
||||
}
|
||||
|
||||
function litefm_path_within_home($homePath, $candidatePath)
|
||||
{
|
||||
$homeNorm = str_replace('\\', '/', clean_path((string)$homePath));
|
||||
$candidateNorm = str_replace('\\', '/', clean_path((string)$candidatePath));
|
||||
$homeCmp = strtolower(rtrim($homeNorm, '/'));
|
||||
$candidateCmp = strtolower($candidateNorm);
|
||||
if ($candidateCmp === $homeCmp) {
|
||||
return true;
|
||||
}
|
||||
return strpos($candidateCmp, $homeCmp . '/') === 0;
|
||||
}
|
||||
|
||||
function litefm_safe_join_home_path($homePath, $relativePath)
|
||||
{
|
||||
$normalizedRel = litefm_normalize_relative_path($relativePath);
|
||||
if ($normalizedRel === false) {
|
||||
return false;
|
||||
}
|
||||
$fullPath = clean_path(rtrim((string)$homePath, '/') . '/' . $normalizedRel);
|
||||
if (!litefm_path_within_home($homePath, $fullPath)) {
|
||||
return false;
|
||||
}
|
||||
return $fullPath;
|
||||
}
|
||||
|
||||
function do_progress($kbytes,$totalsize)
|
||||
{
|
||||
if( $totalsize != 0 )
|
||||
|
|
@ -54,7 +122,12 @@ function litefm_check($home_id)
|
|||
{
|
||||
if (isset($_GET['item']) and !isset($_GET['upload']) and !isset( $_POST['delete'] ) and !isset( $_POST['create_folder'] ) and !isset( $_POST['secureButton'] ) and !isset( $_POST['delete_check'] ) and !isset( $_POST['secure_check'] ))
|
||||
{
|
||||
$fileName = !empty($_POST['name']) ? urldecode($_POST['name']) : urldecode($_GET['name']);
|
||||
$fileName = !empty($_POST['name']) ? litefm_decode_name_param($_POST['name']) : litefm_decode_name_param(isset($_GET['name']) ? $_GET['name'] : '');
|
||||
if (!litefm_is_valid_path_component($fileName))
|
||||
{
|
||||
print_failure("Path decode failed");
|
||||
return FALSE;
|
||||
}
|
||||
if(isset($_GET['type'])){
|
||||
$type = $_GET['type'];
|
||||
}else{
|
||||
|
|
@ -66,23 +139,29 @@ function litefm_check($home_id)
|
|||
|
||||
$path = $_SESSION['fm_files_'.$home_id][$_GET['item']];
|
||||
if($path == $fileName){
|
||||
// Make sure nobody tries to get outside thier game server by referencing the .. directory
|
||||
if(preg_match("/\/\.\.\/|\||;/", $path))
|
||||
if($type != "file"){
|
||||
$nextPath = trim((string)@$_SESSION['fm_cwd_'.$home_id], '/');
|
||||
$nextPath = $nextPath === '' ? $path : $nextPath . '/' . $path;
|
||||
$normalizedNext = litefm_normalize_relative_path($nextPath);
|
||||
if($normalizedNext === false)
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
$_SESSION['fm_cwd_'.$home_id] = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($type != "file"){
|
||||
$_SESSION['fm_cwd_'.$home_id] = @$_SESSION['fm_cwd_'.$home_id] . "/" . $path;
|
||||
$_SESSION['fm_cwd_'.$home_id] = clean_path($_SESSION['fm_cwd_'.$home_id]);
|
||||
$_SESSION['fm_cwd_'.$home_id] = $normalizedNext;
|
||||
}else{
|
||||
if((isset($_SESSION['fm_cwd_'.$home_id]) and !endsWith($_SESSION['fm_cwd_'.$home_id], $path)) or !isset($_SESSION['fm_cwd_'.$home_id])){
|
||||
$_SESSION['fm_cwd_'.$home_id] = @$_SESSION['fm_cwd_'.$home_id] . "/" . $path;
|
||||
$_SESSION['fm_cwd_'.$home_id] = clean_path($_SESSION['fm_cwd_'.$home_id]);
|
||||
$nextPath = trim((string)@$_SESSION['fm_cwd_'.$home_id], '/');
|
||||
$nextPath = $nextPath === '' ? $path : $nextPath . '/' . $path;
|
||||
$normalizedNext = litefm_normalize_relative_path($nextPath);
|
||||
if($normalizedNext === false)
|
||||
{
|
||||
print_failure(get_lang("unallowed_char"));
|
||||
$_SESSION['fm_cwd_'.$home_id] = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
$_SESSION['fm_cwd_'.$home_id] = $normalizedNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,12 +26,23 @@ In-panel file manager and file editor for customer server homes.
|
|||
- remote file listings
|
||||
- read/write operations
|
||||
|
||||
Current listing flow uses `remote_dirlistfm`, where agent filenames are treated as exact values and preserved by the Panel.
|
||||
|
||||
## User Workflow
|
||||
|
||||
- browse files
|
||||
- upload/download
|
||||
- edit common configs
|
||||
|
||||
Special-character names are supported end-to-end in browse/navigation/actions, including:
|
||||
|
||||
- `@3739421199`
|
||||
- `@CF`
|
||||
- `My Mod Folder`
|
||||
- `[Server] Configs`
|
||||
- `profile.backup`
|
||||
- `mod+keys`
|
||||
|
||||
## Admin Workflow
|
||||
|
||||
- set file management permissions
|
||||
|
|
@ -43,9 +54,22 @@ In-panel file manager and file editor for customer server homes.
|
|||
- protected control files
|
||||
- shared secret exposure
|
||||
|
||||
Path safety model:
|
||||
|
||||
- Preserve exact filename display and action values (no destructive filename stripping).
|
||||
- Escape output for HTML rendering only.
|
||||
- Encode filename tokens in links using `rawurlencode`; decode with `rawurldecode`.
|
||||
- Reject invalid path components (`..`, path separators, NUL byte).
|
||||
- Normalize relative paths and verify final resolved paths remain inside the assigned game home.
|
||||
- Distinguish user-facing errors:
|
||||
- `Server files have not been installed yet.` (home missing)
|
||||
- `Directory not found: <relative path>` (missing subdirectory)
|
||||
- `Directory exists but cannot be opened. Check permissions.` (listing/access failure)
|
||||
- `Path decode failed` (invalid filename token)
|
||||
|
||||
## Known Issues
|
||||
|
||||
- should be hardened around safe roots and backups
|
||||
- very large uploads/downloads still depend on chunking/browser limits
|
||||
|
||||
## Missing Functionality
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue