diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/README.md b/README.md index 46e02398..3dead7c7 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,28 @@ `#html` `#css` `#js` `#php` `#master-in-software-development` -# PHP Local FileSystem explorer +# PHP Local FileSystem

Version

->In this project you will have to create a system file explorer that allows the user to navigate, create directories and upload files in the same way as he would in his usual operating system. +![app](assets/readme/app.png) + +>In this project we create a system file explorer that allows the user to navigate, create directories and upload files in the same way as he would in his usual operating system. >The file explorer is a tool that allows you to directly view and manipulate the files and directories associated with a path, so you must take into account from which path the user starts and which path they can access. ## Index -- [Requirements](#requirements) -- [Repository](#repository) -- [Technologies used](#technologies-used) -- [Project delivery](#project-delivery) -- [Resources](#resources) - -## Requirements - -- You cannot use file third-party libraries -- You will not be able to use global variables in PHP. -- You must use GIT -- You must use the PHP > v8 -- Create a clear and orderly directory structure -- Both the code and the comments must be written in English -- Use the camelCase code style to define variables and functions -- In the case of using HTML, never use inline styles -- In the case of using different programming languages ​​always define the implementation in separate terms -- Remember that it is important to divide the tasks into several sub-tasks so that in this way you can associate each particular step of the construction with a specific commit -- You should try as much as possible that the commits and the planned tasks are the same -Delete files that are not used or are not necessary to evaluate the project +- [PHP Local FileSystem](#php-local-filesystem) + - [Wireframe](#wireframe) + - [ShowCase Diagram](#showcase-diagram) + - [Repository](#repository) + +## Wireframe + +![app](assets/readme/wireframe.png) ## Repository @@ -41,20 +31,3 @@ First of all you must fork this project into your GitHub account. To create a fork on GitHub is as easy as clicking the “fork” button on the repository page. Fork on GitHub - -## Technologies used - -\* HTML - -\* CSS - -\* JS - -\* PHP - -## Resources - -- [File system](https://es.wikipedia.org/wiki/Administrador_de_archivos) -- [PHP FileSystem W3C](https://www.w3schools.com/php/php_ref_filesystem.asp) -- [PHP FileSystem Oficial](https://www.php.net/manual/es/book.filesystem.php) -- [README Guidelines Example](https://gist.github.com/PurpleBooth/109311bb0361f32d87a2) diff --git a/advancedSearch.php b/advancedSearch.php new file mode 100644 index 00000000..77dca8c6 --- /dev/null +++ b/advancedSearch.php @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/css/style.css b/css/style.css new file mode 100644 index 00000000..eda7fbc5 --- /dev/null +++ b/css/style.css @@ -0,0 +1,61 @@ +body { + background-color: #f7f7f7; +} + +.folder-btn { + background-color: transparent; + border: none; + padding: 0; +} + +.home-btn { + color: white; +} + +.icon { + max-width: 22px; + max-height: 22px; +} + +.link { + text-decoration: none; + color: black; +} + +.pre { + background-color: white; + padding: 10px 30px; + overflow: scroll; +} + +.p { + margin-left: 30px; +} + + +input[type="file"] { + display: none; +} +.custom-file-upload { + display: inline-block; + padding: 6px 12px; + cursor: pointer; + color: white; +} + +.custom-file-create { + display: inline-block; + padding: 6px 12px; + cursor: pointer; + color: white; +} +i { + font-size: 1.3em; +} +label { + font-size: 1.3em; +} + +form { + display: inline-block; +} diff --git a/delete.php b/delete.php new file mode 100644 index 00000000..74e342b3 --- /dev/null +++ b/delete.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/deleteAll.php b/deleteAll.php new file mode 100644 index 00000000..8add3416 --- /dev/null +++ b/deleteAll.php @@ -0,0 +1,44 @@ + 0) { + foreach ($files as $oldPath) { + $newPath = Utils::changeFileRoute('./trash/', $oldPath); + $name = Utils::getNameFile($oldPath); + $finalName = Utils::chooseName($newPath, $name); + Utils::moveFiles($oldPath, './trash/' . $finalName); + $_SESSION['recovers'][$name] = $oldPath; + } + $msg['folder'] = 'ok'; + } else { + $msg['folder'] = 'is-empty'; + } +} else { // TRASH + if (count($files) > 0) { + foreach ($files as $file) { + if (is_dir($file)) + Utils::deleteAll($file); + else + unlink($file); + + unset($_SESSION['recovers'][Utils::getNameFile($file)]); + } + $msg['trash'] = 'ok'; + } else { + $msg['trash'] = 'is-empty'; + } +} +Utils::saveSession(SESSION); +echo json_encode($msg); \ No newline at end of file diff --git a/destroySession.php b/destroySession.php new file mode 100644 index 00000000..a44f7f67 --- /dev/null +++ b/destroySession.php @@ -0,0 +1,7 @@ + $path, "size" => $size, "type" => $type, "time" => $formattedTime, "relative" => $relativePath]); \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 00000000..9b0a543f --- /dev/null +++ b/index.php @@ -0,0 +1,389 @@ + 0) { + $_SESSION['relativePath'] = $_REQUEST['p']; + $_SESSION['absolutePath'] = $folderPath . '/' . $_REQUEST['p']; + $folderPath = $folderPath . '/' . $_REQUEST['p']; +} else { + $_SESSION['relativePath'] = ''; + $_SESSION['absolutePath'] = ROOT; +} + +if (!isset($_SESSION['moves'])) { + $_SESSION['copies'] = []; + $_SESSION['moves'] = []; +} + +Utils::saveSession(SESSION); + +?> + + + +
+ +
+ +
+ + + Back + + +

TRASH

+
+ +
+
+ + + + + + + + + + + + + + + + +
NameSizeLast ModificationActions
+ 0) { + foreach ($_SESSION['moves'] as $move) { + $route = explode('/', $move); + array_pop($route); + $movePath = implode('/', $route); + } + } else { + foreach ($_SESSION['copies'] as $move) { + $route = explode('/', $move); + array_pop($route); + $movePath = implode('/', $route); + } + } + ?> +
+ +
+ 0) { + ?> + + 0) { + ?> + + 0) { + ?> + > + + Open Trash + + + > + + Open Trash + + +
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/js/ajaxCalls.js b/js/ajaxCalls.js new file mode 100644 index 00000000..2b84d721 --- /dev/null +++ b/js/ajaxCalls.js @@ -0,0 +1,293 @@ +// UPLOAD ///////////////////////////////////////////////////////////////////////////// + +function uploadFile() { + document.getElementById('uploadForm').submit(); +} + +// DELETE ALL AND TRASH /////////////////////////////////////////////////////////////// + +function deleteAll(e, element) { + e.preventDefault(); + fetch(`./deleteAll.php?el=${element}`) + .then(res => res.json()) + .then(res => { + if (res.folder == 'ok') { + document.querySelectorAll('[data-file]').forEach(node => { + node.remove(); + }); + document.querySelector('#emptyAll').style.display = 'none'; + createEmptyRow(true); + const openTrash = document.querySelector('#openTrash'); + openTrash.innerHTML = ''; + openTrash.innerHTML = ' Open Trash'; + new_alert('success', null, "All files deleted successfully!", false, 4000, false); + } else if (res.folder == 'is-empty') { + new_alert('warning', "Warning!", "Empty folder!", true, 4000, true); + } else if (res.trash == 'ok') { + document.querySelectorAll('[data-file]').forEach(node => { + node.remove(); + }); + document.querySelector('#emptyTrash').style.display = 'none'; + createEmptyRow(true); + new_alert('success', null, "All files deleted successfully!", false, 4000, false); + + } else if (res.trash == 'is-empty') { + new_alert('warning', "Warning!", "Empty folder!", true, 4000, true); + } + }) + .catch(() => { + new_alert('error', "Ooops ...", "Something went wrong!", true, 4000, true); + }); +} + +function deleteFile(e, fileName) { + e.preventDefault(); + const file = new FormData(); + file.append("fileName", fileName); + const config = { + 'method': 'POST', + 'body': file, + } + fetch(`./delete.php`, config) + .then(res => res.json()) + .then(res => { + if (res === 'ok') { + document.querySelector(`[data-file='${fileName}']`).remove(); + const openTrash = document.querySelector('#openTrash'); + openTrash.innerHTML = ''; + openTrash.innerHTML = ' Open Trash'; + } + createEmptyRow(false); + new_alert('success', null, "File deleted successfully!", false, 4000, false); + }) + .catch(() => { + new_alert('error', "Ooops ...", "Something went wrong!", true, 4000, true); + }); +} + +// SEARCH ////////////////////////////////////////////////////////////////////////////////// + +function searchFile(e) { + const searchValue = e.target.value; + + const searchData = new FormData(); + searchData.append('search', searchValue) + fetch("./search.php", + { + 'method': 'POST', + 'body': searchData + }) + .then(res => res.json()) + .then(resultFiles => { + let data_files = []; + const files = document.querySelectorAll(`tr[data-file]`); + files.forEach(node => { + data_files.push(node.getAttribute('data-file')); + }); + + data_files.forEach(name => { + resultFiles.forEach(nameResult => { + if (name == nameResult) { + data_files = arrayRemove(data_files, name); + } + }); + }); + files.forEach(node => { + if (data_files.find(name => name.toUpperCase() == node.getAttribute('data-file').toUpperCase())) { + node.style.display = 'none'; + } else { + node.style.display = 'revert'; + } + }); + }) + .catch(() => { + new_alert('error', "Ooops ...", "Something went wrong!", true, 4000, true); + }); + + function arrayRemove(arr, value) { + return arr.filter(function (ele) { + return ele != value; + }); + } +} + +function advancedSearch(e) { + e.preventDefault(); + const searchValue = searchBar.value; + searchBar.value = ''; + const searchData = new FormData(); + searchData.append('search', searchValue); + const fileExtensionsAllowed = ['jpg', 'png', 'txt', 'docx', 'csv', 'ppt', 'odt', 'pdf', 'zip', 'rar', 'exe', 'svg', 'mp3', 'mp4', '0']; + + fetch("advancedSearch.php", { 'method': 'POST', 'body': searchData }) + .then(res => res.json()) + .then(resultFiles => { + const tbody = document.querySelector('#tbody'); + tbody.innerHTML = ''; + resultFiles.forEach(file => { + const array = file.split('\\'); + const name = array[array.length - 1]; + const data = new FormData(); + data.append('name', name); + data.append('path', file) + fetch("./getSearchFiles.php", { 'method': 'POST', 'body': data }) + .then(res => res.json()) + .then(files => { + console.log(files); + let array = name.split('.'); + let extension = array[array.length - 1]; + let icon = ''; + if (fileExtensionsAllowed.includes(extension)) { + icon = extension; + } else icon = 'other'; + + if (files.type === 'dir') { + icon = 'dir'; + href = '?search&p='; + } else href = 'open.php?search&path='; + tbody.innerHTML += `$fileExtension + ${name}${files.size}${files.time} + + `; + }); + }); + }) + .catch(() => { + new_alert('error', "Ooops ...", "Something went wrong!", true, 4000, true); + }); + +} + +// RENAME ////////////////////////////////////////////////////////////////////////////////////////////////// + +function renameFile(e) { + e.preventDefault(); + const newName = rename.value; + const oldName = document.querySelector("#renameTitle").getAttribute("data-file"); + const file = new FormData(); + file.append("newName", newName); + file.append("oldName", oldName); + const config = { + 'method': 'POST', + 'body': file, + } + + fetch("./rename.php", config) + .then(res => res.json()) + .then(async res => { + const name = res; + changeName(oldName, name); + new_alert('success', null, "File renamed successfully!", false, 4000, false); + }) + .catch(function (err) { + console.error(err); + new_alert('error', "Ooops ...", "Something went wrong!", true, 4000, true); + }); + + function changeName(oldName, newName) { + const modify = document.querySelector(`tr[data-file='${oldName}']`); + modify.removeAttribute("data-file"); + modify.setAttribute("data-file", newName); + const link = modify.children[0].children[1]; + link.textContent = newName; + let href = link.href.split("=")[0]; + href += `=${newName}`; + href = href.replace(' ', '%20'); + link.href = href; + } +} + +// MOVE /////////////////////////////////////////////////////////////////////////////////////// + +function copyFile(e) { + e.preventDefault(); + const fileName = e.target.parentNode.getAttribute("data-file"); + const file = new FormData(); + file.append('name', fileName); + file.append('action', 'copy'); + const config = { + 'method': 'POST', + 'body': file, + } + + fetch("./copy_path.php", config) + .then(res => res.json()) + .then((size) => { + addCopyAction(e); + if(size==1){ + new_alert('info', "Press ESC to cancel","",true, 0, false); + } + }) + .catch(() => { + new_alert('error', "Ooops ...", "Something went wrong!", true, 4000, true); + }); +} + +function moveFile(e) { + e.preventDefault(); + const fileName = e.target.parentNode.getAttribute("data-file"); + const file = new FormData(); + file.append('name', fileName); + file.append('action', 'move'); + const config = { + 'method': 'POST', + 'body': file, + } + + fetch("./copy_path.php", config) + .then(res => res.json()) + .then((size) => { + addMoveAction(e); + if(size == 1){ + new_alert('info', "Press ESC to cancel","",true, 0, false); + } + }) + .catch(() => { + new_alert('error', "Ooops ...", "Something went wrong!", true, 4000, true); + }); +} + +// RECOVER TRASH ////////////////////////////////////////////////////////////////////////// + +function recoverFile(e) { + let name = ''; + if (e.target.tagName == 'I') { + name = e.target.parentNode.parentNode.parentNode.getAttribute('data-file'); + } else { + name = e.target.parentNode.parentNode.getAttribute('data-file'); + } + + fetch(`./recover.php?filename=${name}`) + .then(res => res.json()) + .then(() => { + document.querySelector(`tr[data-file="${name}"]`).remove(); + createEmptyRow(false); + new_alert('success', null, "File recovered successfully!", false, 4000, false); + }) + .catch(() => { + new_alert('error', "Ooops ...", "Something went wrong!", true, 4000, true); + }); +} + +function createEmptyRow(isEmpty) { + if (isEmpty) { + createRow(); + } else { + if (document.querySelectorAll('tr[data-file]').length === 0) { + createRow(); + } + } + + function createRow() { + const tr = document.createElement('tr'); + let td = document.createElement('td'); + td.textContent = 'No files were found'; + td.classList.add('fw-bold'); + td.classList.add('p-3'); + tr.append(td); + tr.innerHTML += ''; + const tbody = document.querySelector('#tbody'); + tbody.append(tr); + } +} + diff --git a/js/alert.js b/js/alert.js new file mode 100644 index 00000000..dd50e80b --- /dev/null +++ b/js/alert.js @@ -0,0 +1,12 @@ + +function new_alert(i, title, text, btn, time, timer) { + Swal.fire({ + position: 'center', + icon: i, + title: title, + text: text, + showConfirmButton: btn, + timer: time, + timerProgressBar: true + }); +} \ No newline at end of file diff --git a/js/copy.js b/js/copy.js new file mode 100644 index 00000000..7fc6738f --- /dev/null +++ b/js/copy.js @@ -0,0 +1,133 @@ +const renameFunction = document.querySelectorAll('#renameFunction'); +const copyFunction = document.querySelectorAll('#copyFunction'); +const moveFunction = document.querySelectorAll('#moveFunction'); +const deleteFunction = document.querySelectorAll('#deleteFunction'); +const unzipFunction = document.querySelectorAll('#unzipFunction'); +const pasteBtn = document.querySelector('#pasteFunction'); +const emptyAll = document.querySelector('#emptyAll'); +const openTrash = document.querySelector('#openTrash'); +const searchBar = document.querySelector(`#searchBar`); +const createModalBtn = document.querySelector(`#openCreateModal`); +const uploadBtn = document.querySelector(`#uploadForm label`); + +function addMoveAction(e) { + const name = e.target.parentNode.getAttribute('data-file'); + const targets = document.querySelectorAll(`tr[data-file='${name}'] td [data-change]`); // add opacity to row + targets.forEach(node => { + node.style.opacity = 0.2 + }); + e.target.children[0].setAttribute('disabled', ''); // disable cut button + hideExtraOptions(name, 'copy'); + + //document.querySelector(`td[data-file='${fileName}']`).setAttribute('data-no-paste', ''); +} + +function addCopyAction(e) { + const name = e.target.parentNode.getAttribute('data-file'); + const copyIcon = e.target.children[0].children[0]; // change copy actoin color + copyIcon.classList.remove('text-white'); + copyIcon.classList.add('text-primary'); + e.target.children[0].setAttribute('disabled', ''); // disable copy button + hideExtraOptions(name, 'move'); + + //e.target.parentNode.setAttribute('data-no-paste', ''); +} + +function hideExtraOptions(name, option) { + + const allFiles = document.querySelectorAll(`td[data-type='file']`); // avoid click on files + allFiles.forEach(file => { + file.parentNode.children[0].children[1].style.pointerEvents = 'none'; + }); + document.querySelector(`tr[data-file='${name}'] td a`).style.pointerEvents = 'none'; // avoid click on folder if is selected + searchBar.setAttribute('disabled', ''); + createModalBtn.setAttribute('disabled', ''); // disable general functions + createModalBtn.style.cursor = 'default'; + createModalBtn.style.pointerEvents = 'none'; + uploadBtn.style.pointerEvents = 'none'; + uploadBtn.style.cursor = 'default'; + openTrash.style.visibility = 'hidden'; + emptyAll.style.visibility = 'hidden'; + + renameFunction.forEach(node => { // disable specific functions + node.style.visibility = 'hidden'; + }); + deleteFunction.forEach(node => { + node.style.visibility = 'hidden'; + }); + unzipFunction.forEach(node => { + node.style.visibility = 'hidden'; + }); + + if (option === 'move') + moveFunction.forEach(node => { + node.style.visibility = 'hidden'; + }); + else + copyFunction.forEach(node => { + node.style.visibility = 'hidden'; + }); +} + +// CANCEL COPY OR MOVE + +document.onkeydown = function (evt) { + evt = evt || window.event; + var isEscape = false; + if ("key" in evt) { + isEscape = (evt.key === "Escape" || evt.key === "Esc"); + } else { + isEscape = (evt.keyCode === 27); + } + if (isEscape) { + fetch('./removeCopyAndMoveSession.php') + .then(res => res.json()) + .then(res => { + restartPaste(); + }) + } +} + +function restartPaste() { + moveFunction.forEach(el => { + el.style.visibility = 'visible'; + el.parentNode.style.opacity = '1'; + el.children[0].removeAttribute('disabled'); + }); + copyFunction.forEach(el => { + el.style.visibility = 'visible'; + el.children[0].children[0].classList.remove('text-primary'); + el.children[0].children[0].classList.add('text-white'); + el.children[0].removeAttribute('disabled'); + }); + deleteFunction.forEach(el => { + el.style.visibility = 'visible'; + }); + renameFunction.forEach(el => { + el.style.visibility = 'visible'; + }); + unzipFunction.forEach(node => { + node.style.visibility = 'visible'; + }); + document.querySelectorAll('tr[data-file] [data-change]').forEach(el => { + el.style.opacity = 1; + }); + /* document.querySelectorAll('[data-no-paste]').forEach(el => { + el.removeAttribute('data-no-paste'); + }); */ + openTrash.style.visibility = 'visible'; + emptyAll.style.visibility = 'visible'; + pasteBtn.style.display = 'none'; + + const allFiles = document.querySelectorAll(`td[data-type]`); + allFiles.forEach(file => { + file.parentNode.children[0].children[1].style.pointerEvents = 'inherit'; + }); + + document.querySelector(`#searchBar`).removeAttribute('disabled'); + document.querySelector(`#openCreateModal`).removeAttribute('disabled'); + document.querySelector(`#openCreateModal`).style.cursor = 'pointer'; + document.querySelector(`#openCreateModal`).style.pointerEvents = 'inherit'; + document.querySelector(`#uploadForm label`).style.pointerEvents = 'inherit'; + document.querySelector(`#uploadForm label`).style.cursor = 'pointer'; +} diff --git a/js/drag.js b/js/drag.js new file mode 100644 index 00000000..0af6d03b --- /dev/null +++ b/js/drag.js @@ -0,0 +1,60 @@ +document.addEventListener('DOMContentLoaded', (event) => { + + function handleDragStart(e) { + this.style.opacity = '0.8'; + dragSrcEl = this; + + e.dataTransfer.effectAllowed = 'move'; + e.dataTransfer.setData('text/html', this.innerHTML); + } + + function handleDragEnd(e) { + this.style.opacity = '1'; + } + + function handleDragOver(e) { + if (e.preventDefault) { + e.preventDefault(); + } + return false; + } + + function handleDragEnter(e) { + + } + + function handleDragLeave(e) { + + } + + function handleDrop(e) { + e.stopPropagation(); + + const to = document.querySelector(`tr[data-file='${e.target.getAttribute('data-tr')}']`); + const fileFrom = dragSrcEl.getAttribute('data-file'); + const folderTo = to.getAttribute('data-file'); + if ((to.getAttribute('data-type') === 'dir') && fileFrom !== folderTo) { + fetch(`./drop.php?old=${fileFrom}&new=${folderTo}`) + .then(res => res.json()) + .then(res => { + console.log(res); + }) + .catch(err => { + console.error(err); + }); + + dragSrcEl.remove(); + } + return false; + } + + let items = document.querySelectorAll('tr[data-file]'); + items.forEach(function (item) { + item.addEventListener('dragstart', handleDragStart); + item.addEventListener('dragover', handleDragOver); + item.addEventListener('dragenter', handleDragEnter); + item.addEventListener('dragleave', handleDragLeave); + item.addEventListener('dragend', handleDragEnd); + item.addEventListener('drop', handleDrop); + }); +}); \ No newline at end of file diff --git a/js/modal.js b/js/modal.js new file mode 100644 index 00000000..5670a8b2 --- /dev/null +++ b/js/modal.js @@ -0,0 +1,65 @@ +const deleteForm = document.querySelector('#deleteForm'); +const renameForm = document.querySelector('#renameForm'); +const deleteTitle = document.querySelector('#deleteTitle'); +const renameTitle = document.querySelector('#renameTitle'); +const renameInput = document.querySelector('#rename'); + +function deleteAllModal() { + deleteForm.onsubmit = function (event) { + return deleteAll(event, 'folder'); + } + deleteTitle.textContent = 'Delete all directories and files'; +} + +function deleteTrashModal() { + deleteForm.onsubmit = function (event) { + return deleteAll(event, 'trash'); + } + deleteTitle.textContent = 'Delete Trash'; +} + +function deleteFileModal(e) { + let name = ''; + if (e.target.tagName == 'I') { + name = e.target.parentNode.parentNode.getAttribute('data-file'); + } else { + name = e.target.parentNode.getAttribute('data-file'); + } + deleteForm.onsubmit = function (event) { + return deleteFile(event, name); + } + deleteTitle.textContent = `Delete ${name}`; +} + +function renameFileModal(e) { + let name = ''; + let type = ''; + if (e.target.tagName == 'I') { + name = e.target.parentNode.parentNode.parentNode.getAttribute('data-file'); + type = e.target.parentNode.parentNode.parentNode.getAttribute('data-type'); + } else { + name = e.target.parentNode.parentNode.getAttribute('data-file'); + type = e.target.parentNode.parentNode.getAttribute('data-type'); + } + let finalName = ''; + if (type === 'file') { + let array = name.split("."); + if (array.length == 1) { + finalName = name; + } + let ext = array.pop(); + if (isNaN(ext)) { + array.forEach((pos, index) => { + if (index > 0) finalName += '.' + pos; + else finalName += pos; + }); + } else { + finalName = name; + } + } else { + finalName = name; + } + renameInput.value = finalName; + renameTitle.textContent = `Rename ${finalName}`; + renameTitle.setAttribute("data-file", name); +} \ No newline at end of file diff --git a/js/session.js b/js/session.js new file mode 100644 index 00000000..f35b4f5e --- /dev/null +++ b/js/session.js @@ -0,0 +1,16 @@ +// CANCEL COPY OR MOVE + +document.onkeydown = function (evt) { + console.log(evt); + evt = evt || window.event; + var isSupr = false; + if ("key" in evt) { + isSupr = (evt.key === "Delete"); + } else { + isSupr = (evt.keyCode === 46); + } + + if (isSupr) { + fetch('./destroySession.php') + } +} diff --git a/open.php b/open.php new file mode 100644 index 00000000..31a6f6f5 --- /dev/null +++ b/open.php @@ -0,0 +1,198 @@ + + + +
+ +
+ +
+ +
+ + +
+

File ""

+

Path: + +

+

Size:

+

MIME-Type: + +

+

Charset:

+
+ + + Download + + + + + Open + + + + + Back + +
+ + +
+                                          
+                                      
+                                          
+                                        
+ +
+                                          
+                                      getEntries();
+                                      foreach ($entries as $entry) {
+                                        $entry = str_replace('RarEntry for file "', "File: ", $entry);
+                                        echo "

" . $entry . "


"; + } + $archive->close(); + ?> +
+
+ +
+                                        
+                                      open($path) === true) {
+                                        for ($i = 0; $i < $zip->numFiles; $i++) {
+                                          $filename = $zip->getNameIndex($i);
+                                          echo "

" . $filename . "


"; + } + $zip->close(); + } + ?> +
+
+ + <?php echo $fileName ?> + + + + + +
+                                    
+                                " . Utils::formatHtml(fread($fileStream, filesize($path))) . "

"; + ?> +
+
+ +
+                                    
+                                
+                                    
+                                  
+ +
+                                    
+                                
+                                    
+                                  
+ + + + 0) { + foreach ($_SESSION['moves'] as $key => $move) { + $newPath = $_SESSION['absolutePath']; + $oldPath = $move; + $finalPath = $newPath . '/' . $key; + $finalName = Utils::chooseName($finalPath, $key); + Utils::moveFiles($oldPath, $newPath . '/' . $finalName); + } + $_SESSION['moves'] = []; + $isCopy = 'false'; +} else { + foreach ($_SESSION['copies'] as $key => $copy) { + $newPath = $_SESSION['absolutePath']; + $oldPath = $copy; + $finalPath = $newPath . '/' . $key; + + if (is_dir($oldPath)) { + $finalName = Utils::chooseName($finalPath, $key); + Utils::copyFilesRecursively($oldPath, $newPath . '/' . $finalName); + } else { + $finalName = Utils::chooseName($finalPath, $key); + copy($oldPath, $newPath . '/' . $finalName); + } + } + $_SESSION['copies'] = []; + $isCopy = 'true'; +} +Utils::saveSession(SESSION); + +if (isset($_SESSION['relativePath'])) { + $returnPath = $_SESSION['relativePath']; +} + +header("Location: index.php?p=$returnPath&isCopy=$isCopy"); \ No newline at end of file diff --git a/recover.php b/recover.php new file mode 100644 index 00000000..526c78fc --- /dev/null +++ b/recover.php @@ -0,0 +1,21 @@ + .jpg, .jpg, .png +2. music => .mp3, videoclips => mp4 +3. Project documents=> .docx, .odt, .pdf diff --git a/root/schedule.csv b/root/schedule.csv new file mode 100644 index 00000000..d950f2c6 --- /dev/null +++ b/root/schedule.csv @@ -0,0 +1,5 @@ +,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday +9.00-12.00,,,,,,, +12.00-15.00,,,,,,, +15.00-18.00,,,,,,, +18.00-21-00,,,,,,, \ No newline at end of file diff --git a/search.php b/search.php new file mode 100644 index 00000000..afc1fa1e --- /dev/null +++ b/search.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/sessionfile.txt b/sessionfile.txt new file mode 100644 index 00000000..0c22a932 --- /dev/null +++ b/sessionfile.txt @@ -0,0 +1 @@ +relativePath|s:0:"";absolutePath|s:6:"./root";copies|a:0:{}moves|a:3:{s:11:"Introtp.rar";s:18:"./root/Introtp.rar";s:11:"Introtp.mp4";s:18:"./root/Introtp.mp4";s:5:"Music";s:12:"./root/Music";}recovers|a:6:{s:7:"Introtp";s:14:"./root/Introtp";s:5:"cats2";s:19:"./root/Images/cats2";s:13:"new kitty.jpg";s:32:"./root/Images/cats/new kitty.jpg";s:9:"image.jpg";s:28:"./root/Images/cats/image.jpg";s:33:"php_rar-4.2.0-8.1-ts-vs16-x64.zip";s:40:"./root/php_rar-4.2.0-8.1-ts-vs16-x64.zip";s:8:"fdsa.txt";s:15:"./root/fdsa.txt";} \ No newline at end of file diff --git a/templates/footer.php b/templates/footer.php new file mode 100644 index 00000000..3c1d34c2 --- /dev/null +++ b/templates/footer.php @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/templates/header.php b/templates/header.php new file mode 100644 index 00000000..f5bb739f --- /dev/null +++ b/templates/header.php @@ -0,0 +1,23 @@ + + + + + + + + Files Explorer + + + + + + + + + + + \ No newline at end of file diff --git a/templates/load.php b/templates/load.php new file mode 100644 index 00000000..6bdf2d92 --- /dev/null +++ b/templates/load.php @@ -0,0 +1,410 @@ + 1) { + paintBackRow(); + } + $dirs = []; + $filesInDir = []; + foreach ($files as $file) { + if (filetype($path . '/' . $file) == 'dir') + array_push($dirs, $file); + else + array_push($filesInDir, $file); + } + + foreach ($dirs as $dir) { + paintFile($path, $dir, $options); + } + foreach ($filesInDir as $file) { + paintFile($path, $file, $options); + } + if (count($files) == 0) { +?> + + No files were found + + + + + + 0 + ? $_REQUEST['p'] . '/' . $file + : $file; + createFileRow($absolutePath, $relativePath, $file, true, false, $options); + } else { // Primera apertura sin navegación + + createFileRow($absolutePath, null, $file, true, true, $options); + } + } else { // Si es un archivo + createFileRow($absolutePath, null, $file, false, false, $options); + } +}; + +function createFileRow($absolutePath, $relativePath, $fileName, $isFolder, $isRoot, $options) +{ +?> + data-file="" data-type=""> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + data-change style="cursor: inherit; opacity: 0.2; pointer-events:none"> + + + + data-change style="cursor: inherit; pointer-events:none"> + + + + + + + + data-change data-tr=""> + + + + + + + + + + + + + ' . Utils::formatSize(filesize($absolutePath)) . '

'; + } else { + echo "

" . Utils::formatSize(filesize($absolutePath)) . '

'; + } + ?> + + + + ' . date("D d M Y", $fecha_f) . '

'; + } else { + echo "

" . date("D d M Y", $fecha_f) . '

'; + } + ?> + + + + + + + + + + + +
+ +
+ 0 || count($_SESSION['moves']) > 0) { + ?> + + +
+ +
+ +
+ +
+ 0 || count($_SESSION['moves']) > 0) { + ?> + + +
+ +
+ +
id="unzipFunction"> + + +
+ + + + + + + + + + + + + + + + + + + . . + + + + + + +"; +} + +function updateNavigationBreadcrum($dirName) +{ +?> + + 0 || count($_SESSION['copies']) > 0) + return true; + return false; +} +?> \ No newline at end of file diff --git a/trash/Introtp/Introtp.mp4 b/trash/Introtp/Introtp.mp4 new file mode 100644 index 00000000..6b2a0bf6 Binary files /dev/null and b/trash/Introtp/Introtp.mp4 differ diff --git a/trash/cats2/image.jpg b/trash/cats2/image.jpg new file mode 100644 index 00000000..83f7aac0 Binary files /dev/null and b/trash/cats2/image.jpg differ diff --git a/trash/cats2/new kitty.jpg b/trash/cats2/new kitty.jpg new file mode 100644 index 00000000..7d5542f9 Binary files /dev/null and b/trash/cats2/new kitty.jpg differ diff --git a/trash/fdsa.txt b/trash/fdsa.txt new file mode 100644 index 00000000..65a948c5 --- /dev/null +++ b/trash/fdsa.txt @@ -0,0 +1 @@ +Documento de texto \ No newline at end of file diff --git a/trash/image (1).jpg b/trash/image (1).jpg new file mode 100644 index 00000000..83f7aac0 Binary files /dev/null and b/trash/image (1).jpg differ diff --git a/trash/image.jpg b/trash/image.jpg new file mode 100644 index 00000000..83f7aac0 Binary files /dev/null and b/trash/image.jpg differ diff --git a/trash/new kitty (1).jpg b/trash/new kitty (1).jpg new file mode 100644 index 00000000..7d5542f9 Binary files /dev/null and b/trash/new kitty (1).jpg differ diff --git a/trash/new kitty.jpg b/trash/new kitty.jpg new file mode 100644 index 00000000..7d5542f9 Binary files /dev/null and b/trash/new kitty.jpg differ diff --git a/trash/php_rar-4.2.0-8.1-ts-vs16-x64.zip b/trash/php_rar-4.2.0-8.1-ts-vs16-x64.zip new file mode 100644 index 00000000..08fd0636 Binary files /dev/null and b/trash/php_rar-4.2.0-8.1-ts-vs16-x64.zip differ diff --git a/unzip.php b/unzip.php new file mode 100644 index 00000000..d30a07cc --- /dev/null +++ b/unzip.php @@ -0,0 +1,23 @@ + 4000000) { + $errors[] = "File exceeds maximum size (4MB)"; +} + +if (empty($errors)) { + $didUpload = move_uploaded_file($fileTmpName, $uploadDirectory); +} + + +if (isset($_SESSION['relativePath'])) { + $returnPath = $_SESSION['relativePath']; +} + +header("Location: index.php?p=$returnPath"); \ No newline at end of file diff --git a/utils/pdf.php b/utils/pdf.php new file mode 100644 index 00000000..c3ae1c6a --- /dev/null +++ b/utils/pdf.php @@ -0,0 +1,331 @@ +decodedtext = ''; + $this->filename = $filename; + } + + function output($echo = false) { + if($echo) echo $this->decodedtext; + else return $this->decodedtext; + } + + function setUnicode($input) { + // 4 for unicode. But 2 should work in most cases just fine + if($input == true) $this->multibyte = 4; + else $this->multibyte = 2; + } + + function decodePDF() { + // Read the data from pdf file + $infile = @file_get_contents($this->filename, FILE_BINARY); + if (empty($infile)) + return ""; + + // Get all text data. + $transformations = array(); + $texts = array(); + + // Get the list of all objects. + preg_match_all("#obj[\n|\r](.*)endobj[\n|\r]#ismU", $infile, $objects); + $objects = @$objects[1]; + + // Select objects with streams. + for ($i = 0; $i < count($objects); $i++) { + $currentObject = $objects[$i]; + + // Check if an object includes data stream. + if (preg_match("#stream[\n|\r](.*)endstream[\n|\r]#ismU", $currentObject, $stream)) { + $stream = ltrim($stream[1]); + + // Check object parameters and look for text data. + $options = $this->getObjectOptions($currentObject); + + if (!(empty($options["Length1"]) && empty($options["Type"]) && empty($options["Subtype"]))) + continue; + + // Hack, length doesnt always seem to be correct + unset($options["Length"]); + + // So, we have text data. Decode it. + $data = $this->getDecodedStream($stream, $options); + + if (strlen($data)) { + if (preg_match_all("#BT[\n|\r](.*)ET[\n|\r]#ismU", $data, $textContainers)) { + $textContainers = @$textContainers[1]; + $this->getDirtyTexts($texts, $textContainers); + } else + $this->getCharTransformations($transformations, $data); + } + } + } + + // Analyze text blocks taking into account character transformations and return results. + $this->decodedtext = $this->getTextUsingTransformations($texts, $transformations); + } + + + function decodeAsciiHex($input) { + $output = ""; + + $isOdd = true; + $isComment = false; + + for($i = 0, $codeHigh = -1; $i < strlen($input) && $input[$i] != '>'; $i++) { + $c = $input[$i]; + + if($isComment) { + if ($c == '\r' || $c == '\n') + $isComment = false; + continue; + } + + switch($c) { + case '\0': case '\t': case '\r': case '\f': case '\n': case ' ': break; + case '%': + $isComment = true; + break; + + default: + $code = hexdec($c); + if($code === 0 && $c != '0') + return ""; + + if($isOdd) + $codeHigh = $code; + else + $output .= chr($codeHigh * 16 + $code); + + $isOdd = !$isOdd; + break; + } + } + + if($input[$i] != '>') + return ""; + + if($isOdd) + $output .= chr($codeHigh * 16); + + return $output; + } + + function decodeAscii85($input) { + $output = ""; + + $isComment = false; + $ords = array(); + + for($i = 0, $state = 0; $i < strlen($input) && $input[$i] != '~'; $i++) { + $c = $input[$i]; + + if($isComment) { + if ($c == '\r' || $c == '\n') + $isComment = false; + continue; + } + + if ($c == '\0' || $c == '\t' || $c == '\r' || $c == '\f' || $c == '\n' || $c == ' ') + continue; + if ($c == '%') { + $isComment = true; + continue; + } + if ($c == 'z' && $state === 0) { + $output .= str_repeat(chr(0), 4); + continue; + } + if ($c < '!' || $c > 'u') + return ""; + + $code = ord($input[$i]) & 0xff; + $ords[$state++] = $code - ord('!'); + + if ($state == 5) { + $state = 0; + for ($sum = 0, $j = 0; $j < 5; $j++) + $sum = $sum * 85 + $ords[$j]; + for ($j = 3; $j >= 0; $j--) + $output .= chr($sum >> ($j * 8)); + } + } + if ($state === 1) + return ""; + elseif ($state > 1) { + for ($i = 0, $sum = 0; $i < $state; $i++) + $sum += ($ords[$i] + ($i == $state - 1)) * pow(85, 4 - $i); + for ($i = 0; $i < $state - 1; $i++) + $ouput .= chr($sum >> ((3 - $i) * 8)); + } + + return $output; + } + + function decodeFlate($input) { + return gzuncompress($input); + } + + function getObjectOptions($object) { + $options = array(); + + if (preg_match("#<<(.*)>>#ismU", $object, $options)) { + $options = explode("/", $options[1]); + @array_shift($options); + + $o = array(); + for ($j = 0; $j < @count($options); $j++) { + $options[$j] = preg_replace("#\s+#", " ", trim($options[$j])); + if (strpos($options[$j], " ") !== false) { + $parts = explode(" ", $options[$j]); + $o[$parts[0]] = $parts[1]; + } else + $o[$options[$j]] = true; + } + $options = $o; + unset($o); + } + + return $options; + } + + function getDecodedStream($stream, $options) { + $data = ""; + if (empty($options["Filter"])) + $data = $stream; + else { + $length = !empty($options["Length"]) ? $options["Length"] : strlen($stream); + $_stream = substr($stream, 0, $length); + + foreach ($options as $key => $value) { + if ($key == "ASCIIHexDecode") + $_stream = $this->decodeAsciiHex($_stream); + if ($key == "ASCII85Decode") + $_stream = $this->decodeAscii85($_stream); + if ($key == "FlateDecode") + $_stream = $this->decodeFlate($_stream); + if ($key == "Crypt") { // TO DO + } + } + $data = $_stream; + } + return $data; + } + function getDirtyTexts(&$texts, $textContainers) { + + for ($j = 0; $j < count($textContainers); $j++) { + if (preg_match_all("#\[(.*)\]\s*TJ[\n|\r]#ismU", $textContainers[$j], $parts)) + $texts = array_merge($texts, @$parts[1]); + elseif(preg_match_all("#T[d|w|m|f]\s*(\(.*\))\s*Tj[\n|\r]#ismU", $textContainers[$j], $parts)) + $texts = array_merge($texts, @$parts[1]); + elseif(preg_match_all("#T[d|w|m|f]\s*(\[.*\])\s*Tj[\n|\r]#ismU", $textContainers[$j], $parts)) + $texts = array_merge($texts, @$parts[1]); + } + } + function getCharTransformations(&$transformations, $stream) { + preg_match_all("#([0-9]+)\s+beginbfchar(.*)endbfchar#ismU", $stream, $chars, PREG_SET_ORDER); + preg_match_all("#([0-9]+)\s+beginbfrange(.*)endbfrange#ismU", $stream, $ranges, PREG_SET_ORDER); + + for ($j = 0; $j < count($chars); $j++) { + $count = $chars[$j][1]; + $current = explode("\n", trim($chars[$j][2])); + for ($k = 0; $k < $count && $k < count($current); $k++) { + if (preg_match("#<([0-9a-f]{2,4})>\s+<([0-9a-f]{4,512})>#is", trim($current[$k]), $map)) + $transformations[str_pad($map[1], 4, "0")] = $map[2]; + } + } + for ($j = 0; $j < count($ranges); $j++) { + $count = $ranges[$j][1]; + $current = explode("\n", trim($ranges[$j][2])); + for ($k = 0; $k < $count && $k < count($current); $k++) { + if (preg_match("#<([0-9a-f]{4})>\s+<([0-9a-f]{4})>\s+<([0-9a-f]{4})>#is", trim($current[$k]), $map)) { + $from = hexdec($map[1]); + $to = hexdec($map[2]); + $_from = hexdec($map[3]); + + for ($m = $from, $n = 0; $m <= $to; $m++, $n++) + $transformations[sprintf("%04X", $m)] = sprintf("%04X", $_from + $n); + } elseif (preg_match("#<([0-9a-f]{4})>\s+<([0-9a-f]{4})>\s+\[(.*)\]#ismU", trim($current[$k]), $map)) { + $from = hexdec($map[1]); + $to = hexdec($map[2]); + $parts = preg_split("#\s+#", trim($map[3])); + + for ($m = $from, $n = 0; $m <= $to && $n < count($parts); $m++, $n++) + $transformations[sprintf("%04X", $m)] = sprintf("%04X", hexdec($parts[$n])); + } + } + } + } + function getTextUsingTransformations($texts, $transformations) { + $document = ""; + for ($i = 0; $i < count($texts); $i++) { + $isHex = false; + $isPlain = false; + + $hex = ""; + $plain = ""; + for ($j = 0; $j < strlen($texts[$i]); $j++) { + $c = $texts[$i][$j]; + switch($c) { + case "<": + $hex = ""; + $isHex = true; + break; + case ">": + $hexs = str_split($hex, $this->multibyte); // 2 or 4 (UTF8 or ISO) + for ($k = 0; $k < count($hexs); $k++) { + $chex = str_pad($hexs[$k], 4, "0"); // Add tailing zero + if (isset($transformations[$chex])) + $chex = $transformations[$chex]; + $document .= html_entity_decode("&#x".$chex.";"); + } + $isHex = false; + break; + case "(": + $plain = ""; + $isPlain = true; + break; + case ")": + $document .= $plain; + $isPlain = false; + break; + case "\\": + $c2 = $texts[$i][$j + 1]; + if (in_array($c2, array("\\", "(", ")"))) $plain .= $c2; + elseif ($c2 == "n") $plain .= '\n'; + elseif ($c2 == "r") $plain .= '\r'; + elseif ($c2 == "t") $plain .= '\t'; + elseif ($c2 == "b") $plain .= '\b'; + elseif ($c2 == "f") $plain .= '\f'; + elseif ($c2 >= '0' && $c2 <= '9') { + $oct = preg_replace("#[^0-9]#", "", substr($texts[$i], $j + 1, 3)); + $j += strlen($oct) - 1; + $plain .= html_entity_decode("&#".octdec($oct).";", $this->convertquotes); + } + $j++; + break; + + default: + if ($isHex) + $hex .= $c; + if ($isPlain) + $plain .= $c; + break; + } + } + $document .= "\n"; + } + + return $document; + } +} +?> \ No newline at end of file diff --git a/utils/utils.php b/utils/utils.php new file mode 100644 index 00000000..1f73ba0a --- /dev/null +++ b/utils/utils.php @@ -0,0 +1,216 @@ + 0) { + $base = log($size, 1024); + $suffixes = array('bytes', 'kb', 'mb', 'gb', 'tb'); + return round(pow(1024, $base - floor($base)), $precision) . ' ' . $suffixes[floor($base)]; + } else + return ''; + } + + public static function getBreadcrumb($path) + { + return explode('/', $path); + } + + public static function formatHtml($data) + { + $data = ltrim($data); + $data = stripslashes($data); + $data = htmlspecialchars($data); + return $data; + } + + public static function formatDocx($fileName) + { + $striped_content = ''; + $content = ''; + if (!$fileName || !file_exists($fileName)) + return false; + $zip = zip_open($fileName); + if (!$zip || is_numeric($zip)) + return false; + while ($zip_entry = zip_read($zip)) { + if (zip_entry_open($zip, $zip_entry) == FALSE) + continue; + if (zip_entry_name($zip_entry) != "word/document.xml") + continue; + $content .= zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)); + zip_entry_close($zip_entry); + } + zip_close($zip); + $content = str_replace('', " ", $content); + $content = str_replace('', "\r\n", $content); + $striped_content = strip_tags($content); + return $striped_content; + } + + public static function formatPdf($file) + { + $a = new PDF2Text(); + $a->setFilename($file); + $a->decodePDF(); + echo $a->output(); + } + + public static function formatCsv($file) + { + $row = 1; + if (($handle = fopen($file, "r")) !== FALSE) { + while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { + $num = count($data); + $row++; + for ($c = 0; $c < $num; $c++) { + echo "

" . $data[$c] . "

"; + } + } + fclose($handle); + } + } + + public static function formatRar($file, $pathToExtract, $fileName) + { + $archive = RarArchive::open($file); + $entries = $archive->getEntries(); + if (!mkdir($pathToExtract . '/' . explode('.', $fileName)[0])) + return false; + foreach ($entries as $entry) { + $entry->extract($pathToExtract . '/' . explode('.', $fileName)[0]); + } + $archive->close(); + return true; + } + + public static function formatZip($file, $pathToExtract, $fileName) + { + $zip = new ZipArchive; + if ($zip->open($file) === TRUE) { + if (!mkdir($pathToExtract . '/' . explode('.', $fileName)[0])) + return false; + $zip->extractTo($pathToExtract . '/' . explode('.', $fileName)[0]); + $zip->close(); + } else { + echo 'failed to unzip file'; + } + return true; + } + + public static function moveFiles($old, $new) + { + if (file_exists($old) && ((!file_exists($new)) || is_writable($new))) { + rename($old, rtrim($new, '.')); + } + } + + public static function copyFilesRecursively($old, $new) + { + echo "Nombre . " . $new . '
'; + mkdir(rtrim($new, '.'), 0777); + foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($old, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) { + if ($item->isDir()) { + mkdir($new . DIRECTORY_SEPARATOR . $iterator->getSubPathname()); + } else { + copy($item, $new . DIRECTORY_SEPARATOR . $iterator->getSubPathname()); + } + } + } + + public static function deleteAll($dir) + { + foreach (glob($dir . '/*') as $file) { + if (is_dir($file)) + self::deleteAll($file); + else + unlink($file); + } + rmdir($dir); + } + + public static function getDirContents($dir, &$results = array()) + { + $files = scandir($dir); + + foreach ($files as $key => $value) { + $path = realpath($dir . DIRECTORY_SEPARATOR . $value); + if (!is_dir($path)) { + $results[] = $path; + } else if ($value != "." && $value != "..") { + self::getDirContents($path, $results); + $results[] = $path; + } + } + return $results; + } + + public static function changeFileRoute($newPath, $oldPath) + { + $array = explode('/', $oldPath); + return $newPath . $array[count($array) - 1]; + } + + public static function chooseName($path, $name) + { + $actual_name = pathinfo($name, PATHINFO_FILENAME); + $original_name = $actual_name; + $extension = pathinfo($name, PATHINFO_EXTENSION); + $array = explode('/', $path); + array_pop($array); + $path = implode('/', $array); + $i = 1; + while (file_exists($path . '/' . $actual_name . "." . $extension)) { + $actual_name = (string) $original_name . " ($i)"; + $name = $actual_name . "." . $extension; + $i++; + } + return $name; + } + + public static function getFilePermissions($file) + { + return substr(sprintf('%o', fileperms($file)), -4); + } + + public static function saveSession($file) + { + $sessionfile = fopen($file, "w"); + fputs($sessionfile, session_encode()); + fclose($sessionfile); + } +} \ No newline at end of file