diff --git a/.tmp/.gitignore b/.tmp/.gitignore new file mode 100644 index 000000000..a3a0c8b5f --- /dev/null +++ b/.tmp/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index c3fa63fd2..2b3ae8064 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,11 +6,11 @@ WORKDIR /var/www/html # Update packages and install dependencies RUN apk upgrade --no-cache && \ - apk add --no-cache sqlite-dev libpng libpng-dev libjpeg-turbo libjpeg-turbo-dev freetype freetype-dev curl autoconf libgomp icu-dev nginx dcron tzdata imagemagick imagemagick-dev && \ + apk add --no-cache sqlite-dev libpng libpng-dev libjpeg-turbo libjpeg-turbo-dev freetype freetype-dev curl autoconf libgomp icu-dev nginx dcron tzdata imagemagick imagemagick-dev libzip-dev && \ docker-php-ext-install pdo pdo_sqlite && \ docker-php-ext-enable pdo pdo_sqlite && \ docker-php-ext-configure gd --with-freetype --with-jpeg && \ - docker-php-ext-install -j$(nproc) gd intl && \ + docker-php-ext-install -j$(nproc) gd intl zip && \ apk add --no-cache --virtual .build-deps $PHPIZE_DEPS && \ pecl install imagick && \ docker-php-ext-enable imagick && \ diff --git a/README.md b/README.md index 93da5076d..e6353c984 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ See instructions to run Wallos below. - intl - openssl - sqlite3 + - zip #### Docker diff --git a/endpoints/db/backup.php b/endpoints/db/backup.php new file mode 100644 index 000000000..9f7948c1c --- /dev/null +++ b/endpoints/db/backup.php @@ -0,0 +1,71 @@ + false, + "message" => translate('session_expired', $i18n) + ])); +} + +function addFolderToZip($dir, $zipArchive, $zipdir = ''){ + if (is_dir($dir)) { + if ($dh = opendir($dir)) { + //Add the directory + if(!empty($zipdir)) $zipArchive->addEmptyDir($zipdir); + while (($file = readdir($dh)) !== false) { + // Skip '.' and '..' + if ($file == "." || $file == "..") { + continue; + } + //If it's a folder, run the function again! + if(is_dir($dir . $file)){ + $newdir = $dir . $file . '/'; + addFolderToZip($newdir, $zipArchive, $zipdir . $file . '/'); + }else{ + //Add the files + $zipArchive->addFile($dir . $file, $zipdir . $file); + } + } + } + } else { + die(json_encode([ + "success" => false, + "message" => "Directory does not exist: $dir" + ])); + } +} + +$zip = new ZipArchive(); +$filename = "backup_" . uniqid() . ".zip"; +$zipname = "../../.tmp/" . $filename; + +if ($zip->open($zipname, ZipArchive::CREATE)!==TRUE) { + die(json_encode([ + "success" => false, + "message" => translate('cannot_open_zip', $i18n) + ])); +} + +addFolderToZip('../../db/', $zip); +addFolderToZip('../../images/uploads/', $zip); + +$numberOfFilesAdded = $zip->numFiles; + +if ($zip->close() === false) { + die(json_encode([ + "success" => false, + "message" => "Failed to finalize the zip file" + ])); +} else { + flush(); + die(json_encode([ + "success" => true, + "message" => "Zip file created successfully", + "numFiles" => $numberOfFilesAdded, + "file" => $filename + ])); +} + + +?> \ No newline at end of file diff --git a/endpoints/db/import.php b/endpoints/db/import.php new file mode 100644 index 000000000..38672e1d0 --- /dev/null +++ b/endpoints/db/import.php @@ -0,0 +1,112 @@ +query("SELECT COUNT(*) as count FROM user"); +$row = $result->fetchArray(SQLITE3_NUM); +if ($row[0] > 0) { + die(json_encode([ + "success" => false, + "message" => "Denied" + ])); +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + if (isset($_FILES['file'])) { + $file = $_FILES['file']; + $fileTmpName = $file['tmp_name']; + $fileError = $file['error']; + + if ($fileError === 0) { + $fileDestination = '../../.tmp/restore.zip'; + move_uploaded_file($fileTmpName, $fileDestination); + + $zip = new ZipArchive(); + if ($zip->open($fileDestination) === true) { + $zip->extractTo('../../.tmp/restore/'); + $zip->close(); + } else { + die(json_encode([ + "success" => false, + "message" => "Failed to extract the uploaded file" + ])); + } + + if (file_exists('../../.tmp/restore/wallos.db')) { + if (file_exists('../../db/wallos.db')) { + unlink('../../db/wallos.db'); + } + rename('../../.tmp/restore/wallos.db', '../../db/wallos.db'); + + if (file_exists('../../.tmp/restore/logos/')) { + $dir = '../../images/uploads/logos/'; + $di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS); + $ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST); + + foreach ( $ri as $file ) { + if ( $file->isDir() ) { + rmdir($file->getPathname()); + } else { + unlink($file->getPathname()); + } + } + + $dir = new RecursiveDirectoryIterator('../../.tmp/restore/logos/'); + $ite = new RecursiveIteratorIterator($dir); + $allowedExtensions = ['png', 'jpg', 'jpeg', 'gif', 'webp']; + + foreach ($ite as $filePath) { + if (in_array(pathinfo($filePath, PATHINFO_EXTENSION), $allowedExtensions)) { + $destination = str_replace('../../.tmp/restore/', '../../images/uploads/', $filePath); + $destinationDir = pathinfo($destination, PATHINFO_DIRNAME); + + if (!is_dir($destinationDir)) { + mkdir($destinationDir, 0755, true); + } + + copy($filePath, $destination); + } + } + } + + $files = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator('../../.tmp', RecursiveDirectoryIterator::SKIP_DOTS), + RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($files as $fileinfo) { + $removeFunction = ($fileinfo->isDir() ? 'rmdir' : 'unlink'); + $removeFunction($fileinfo->getRealPath()); + } + + echo json_encode([ + "success" => true, + "message" => translate("success", $i18n) + ]); + } else { + die(json_encode([ + "success" => false, + "message" => "wallos.db does not exist in the backup file" + ])); + } + + + } else { + echo json_encode([ + "success" => false, + "message" => "Failed to upload file" + ]); + } + } else { + echo json_encode([ + "success" => false, + "message" => "No file uploaded" + ]); + } +} else { + echo json_encode([ + "success" => false, + "message" => "Invalid request method" + ]); +} +?> \ No newline at end of file diff --git a/endpoints/db/restore.php b/endpoints/db/restore.php new file mode 100644 index 000000000..60a271e41 --- /dev/null +++ b/endpoints/db/restore.php @@ -0,0 +1,109 @@ + false, + "message" => translate('session_expired', $i18n) + ])); +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + if (isset($_FILES['file'])) { + $file = $_FILES['file']; + $fileTmpName = $file['tmp_name']; + $fileError = $file['error']; + + if ($fileError === 0) { + $fileDestination = '../../.tmp/restore.zip'; + move_uploaded_file($fileTmpName, $fileDestination); + + $zip = new ZipArchive(); + if ($zip->open($fileDestination) === true) { + $zip->extractTo('../../.tmp/restore/'); + $zip->close(); + } else { + die(json_encode([ + "success" => false, + "message" => "Failed to extract the uploaded file" + ])); + } + + if (file_exists('../../.tmp/restore/wallos.db')) { + if (file_exists('../../db/wallos.db')) { + unlink('../../db/wallos.db'); + } + rename('../../.tmp/restore/wallos.db', '../../db/wallos.db'); + + if (file_exists('../../.tmp/restore/logos/')) { + $dir = '../../images/uploads/logos/'; + $di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS); + $ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST); + + foreach ( $ri as $file ) { + if ( $file->isDir() ) { + rmdir($file->getPathname()); + } else { + unlink($file->getPathname()); + } + } + + $dir = new RecursiveDirectoryIterator('../../.tmp/restore/logos/'); + $ite = new RecursiveIteratorIterator($dir); + $allowedExtensions = ['png', 'jpg', 'jpeg', 'gif', 'webp']; + + foreach ($ite as $filePath) { + if (in_array(pathinfo($filePath, PATHINFO_EXTENSION), $allowedExtensions)) { + $destination = str_replace('../../.tmp/restore/', '../../images/uploads/', $filePath); + $destinationDir = pathinfo($destination, PATHINFO_DIRNAME); + + if (!is_dir($destinationDir)) { + mkdir($destinationDir, 0755, true); + } + + copy($filePath, $destination); + } + } + } + + $files = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator('../../.tmp', RecursiveDirectoryIterator::SKIP_DOTS), + RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($files as $fileinfo) { + $removeFunction = ($fileinfo->isDir() ? 'rmdir' : 'unlink'); + $removeFunction($fileinfo->getRealPath()); + } + + echo json_encode([ + "success" => true, + "message" => translate("success", $i18n) + ]); + } else { + die(json_encode([ + "success" => false, + "message" => "wallos.db does not exist in the backup file" + ])); + } + + + } else { + echo json_encode([ + "success" => false, + "message" => "Failed to upload file" + ]); + } + } else { + echo json_encode([ + "success" => false, + "message" => "No file uploaded" + ]); + } +} else { + echo json_encode([ + "success" => false, + "message" => "Invalid request method" + ]); +} +?> \ No newline at end of file diff --git a/endpoints/subscriptions/export.php b/endpoints/subscriptions/export.php deleted file mode 100644 index 2b8df91d0..000000000 --- a/endpoints/subscriptions/export.php +++ /dev/null @@ -1,48 +0,0 @@ - false, - "message" => translate('session_expired', $i18n) - ])); -} - -require_once '../../includes/getdbkeys.php'; - -$query = "SELECT * FROM subscriptions"; - -$result = $db->query($query); -if ($result) { - $subscriptions = array(); - while ($row = $result->fetchArray(SQLITE3_ASSOC)) { - // Map foreign keys to their corresponding values - $row['currency'] = $currencies[$row['currency_id']]; - $row['payment_method'] = $payment_methods[$row['payment_method_id']]; - $row['payer_user'] = $members[$row['payer_user_id']]; - $row['category'] = $categories[$row['category_id']]; - $row['cycle'] = $cycles[$row['cycle']]; - $row['frequency'] = $frequencies[$row['frequency']]; - - $subscriptions[] = $row; - } - - // Output JSON - $json = json_encode($subscriptions, JSON_PRETTY_PRINT); - - // Set headers for file download - header('Content-Type: application/json'); - header('Content-Disposition: attachment; filename="subscriptions.json"'); - header('Pragma: no-cache'); - header('Expires: 0'); - - // Output JSON for download - echo $json; -} else { - echo json_encode(array('error' => 'Failed to fetch subscriptions.')); -} - -?> \ No newline at end of file diff --git a/includes/checksession.php b/includes/checksession.php index f7c8610bd..7962690e1 100644 --- a/includes/checksession.php +++ b/includes/checksession.php @@ -8,6 +8,12 @@ $stmt->bindValue(':username', $username, SQLITE3_TEXT); $result = $stmt->execute(); $userData = $result->fetchArray(SQLITE3_ASSOC); + + if ($userData === false) { + header('Location: logout.php'); + exit(); + } + if ($userData['avatar'] == "") { $userData['avatar'] = "0"; } diff --git a/includes/footer.php b/includes/footer.php index b15b6186e..55c8038a0 100644 --- a/includes/footer.php +++ b/includes/footer.php @@ -24,5 +24,11 @@
+ close(); + } + ?> +