├── .dockerignore ├── .github ├── FUNDING.yml └── workflows │ └── build-release.yaml ├── .gitignore ├── .tmp └── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE.md ├── README.md ├── SECURITY.md ├── about.php ├── admin.php ├── api ├── admin │ └── get_admin_settings.php ├── categories │ └── get_categories.php ├── currencies │ └── get_currencies.php ├── fixer │ └── get_fixer.php ├── household │ └── get_household.php ├── notifications │ └── get_notification_settings.php ├── payment_methods │ └── get_payment_methods.php ├── settings │ └── get_settings.php ├── status │ └── version.php ├── subscriptions │ ├── get_ical_feed.php │ ├── get_monthly_cost.php │ └── get_subscriptions.php └── users │ └── get_user.php ├── calendar.php ├── cronjobs ├── db └── wallos.empty.db ├── docker-compose.yaml ├── endpoints ├── admin │ ├── adduser.php │ ├── deleteunusedlogos.php │ ├── deleteuser.php │ ├── saveopenregistrations.php │ ├── savesmtpsettings.php │ └── updatenotification.php ├── categories │ ├── category.php │ └── sort.php ├── cronjobs │ ├── checkforupdates.php │ ├── createdatabase.php │ ├── sendcancellationnotifications.php │ ├── sendnotifications.php │ ├── sendresetpasswordemails.php │ ├── sendverificationemails.php │ ├── settimezone.php │ ├── storetotalyearlycost.php │ ├── updateexchange.php │ ├── updatenextpayment.php │ └── validate.php ├── currency │ ├── add.php │ ├── currency.php │ ├── edit.php │ ├── fixer_api_key.php │ ├── remove.php │ └── update_exchange.php ├── db │ ├── backup.php │ ├── import.php │ ├── migrate.php │ └── restore.php ├── household │ └── household.php ├── logos │ └── search.php ├── notifications │ ├── savediscordnotifications.php │ ├── saveemailnotifications.php │ ├── savegotifynotifications.php │ ├── savenotificationsettings.php │ ├── saventfynotifications.php │ ├── savepushovernotifications.php │ ├── savetelegramnotifications.php │ ├── savewebhooknotifications.php │ ├── testdiscordnotifications.php │ ├── testemailnotifications.php │ ├── testgotifynotifications.php │ ├── testntfynotifications.php │ ├── testpushovernotifications.php │ ├── testtelegramnotifications.php │ └── testwebhooknotifications.php ├── payments │ ├── add.php │ ├── delete.php │ ├── get.php │ ├── payment.php │ ├── rename.php │ ├── search.php │ └── sort.php ├── settings │ ├── colortheme.php │ ├── convert_currency.php │ ├── customcss.php │ ├── customtheme.php │ ├── deleteaccount.php │ ├── disabled_to_bottom.php │ ├── hide_disabled.php │ ├── mobile_navigation.php │ ├── monthly_price.php │ ├── remove_background.php │ ├── resettheme.php │ ├── show_original_price.php │ ├── subscription_progress.php │ └── theme.php ├── subscription │ ├── add.php │ ├── clone.php │ ├── delete.php │ ├── exportcalendar.php │ ├── get.php │ ├── getcalendar.php │ └── renew.php ├── subscriptions │ ├── export.php │ └── get.php └── user │ ├── budget.php │ ├── delete_avatar.php │ ├── disable_totp.php │ ├── enable_totp.php │ ├── regenerateapikey.php │ └── save_user.php ├── images ├── Thumbs.db ├── avatars │ ├── 0.svg │ ├── 1.svg │ ├── 2.svg │ ├── 3.svg │ ├── 4.svg │ ├── 5.svg │ ├── 6.svg │ ├── 7.svg │ ├── 8.svg │ └── 9.svg ├── icon │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon-152.png │ ├── apple-touch-icon-180.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── maskable_icon_x192.png │ └── maskable_icon_x512.png ├── screenshots │ ├── desktop.png │ └── mobile.png ├── siteicons │ ├── payments │ │ ├── Amex.png │ │ ├── ApplePay.png │ │ ├── Bitcoin.png │ │ ├── BitcoinCash.png │ │ ├── DinersClub.png │ │ ├── Discover.png │ │ ├── Etherium.png │ │ ├── Forbrugsforeningen.png │ │ ├── GooglePay.png │ │ ├── Interac.png │ │ ├── JCB.png │ │ ├── Klarna.png │ │ ├── Lightcoin.png │ │ ├── Maestro.png │ │ ├── Mastercard.png │ │ ├── PayPal.png │ │ ├── Payoneer.png │ │ ├── Stripe.png │ │ ├── Thumbs.db │ │ ├── Visa.png │ │ ├── Yandex.png │ │ ├── affirm.png │ │ ├── alipay.png │ │ ├── amazonpay.png │ │ ├── bancontact.png │ │ ├── bitpay.png │ │ ├── citadele.png │ │ ├── directdebit.png │ │ ├── elo.png │ │ ├── facebookpay.png │ │ ├── gitopay.png │ │ ├── ideal.png │ │ ├── paysafe.png │ │ ├── poli.png │ │ ├── qiwi.png │ │ ├── samsungpay.png │ │ ├── shoppay.png │ │ ├── skrill.png │ │ ├── sofort.png │ │ ├── unionpay.png │ │ ├── venmo.png │ │ ├── verifone.png │ │ ├── webmoney.png │ │ └── wechat.png │ ├── pwa │ │ ├── about.png │ │ ├── calendar.png │ │ ├── settings.png │ │ ├── stats.png │ │ └── subscriptions.png │ ├── svg │ │ ├── automatic.php │ │ ├── category.php │ │ ├── check.php │ │ ├── clone.php │ │ ├── delete.php │ │ ├── edit.php │ │ ├── export_ical.php │ │ ├── logo.php │ │ ├── manual.php │ │ ├── mobile-menu │ │ │ ├── about.php │ │ │ ├── admin.php │ │ │ ├── calendar.php │ │ │ ├── clone.php │ │ │ ├── delete.php │ │ │ ├── edit.php │ │ │ ├── home.php │ │ │ ├── logout.php │ │ │ ├── profile.php │ │ │ ├── renew.php │ │ │ ├── settings.php │ │ │ └── statistics.php │ │ ├── notes.php │ │ ├── payment.php │ │ ├── renew.php │ │ ├── save.php │ │ ├── subscription.php │ │ ├── web.php │ │ └── websearch.php │ ├── wallos.png │ └── walloswhite.png ├── siteimages │ ├── Thumbs.db │ ├── empty.png │ ├── emptydark.png │ ├── mobilenav.png │ └── mobilenavdark.png ├── uploads │ └── icons │ │ ├── Thumbs.db │ │ ├── affirm.png │ │ ├── alipay.png │ │ ├── amazonpay.png │ │ ├── applepay.png │ │ ├── banktransfer.png │ │ ├── creditcard.png │ │ ├── crypto.png │ │ ├── directdebit.png │ │ ├── elo.png │ │ ├── facebookpay.png │ │ ├── giropay.png │ │ ├── googlepay.png │ │ ├── ideal.png │ │ ├── interac.png │ │ ├── klarna.png │ │ ├── money.png │ │ ├── paypal.png │ │ ├── paysafe.png │ │ ├── poli.png │ │ ├── qiwi.png │ │ ├── samsungpay.png │ │ ├── sepa.png │ │ ├── shoppay.png │ │ ├── skrill.png │ │ ├── sofort.png │ │ ├── stripe.png │ │ ├── unionpay.png │ │ ├── venmo.png │ │ ├── verifone.png │ │ ├── webmoney.png │ │ └── wechat.png ├── wallossolid.png └── wallossolidwhite.png ├── includes ├── checksession.php ├── checkuser.php ├── connect.php ├── connect_endpoint.php ├── connect_endpoint_crontabs.php ├── currency_formatter.php ├── filters_menu.php ├── footer.php ├── getdbkeys.php ├── getsettings.php ├── header.php ├── i18n │ ├── cs.php │ ├── da.php │ ├── de.php │ ├── el.php │ ├── en.php │ ├── es.php │ ├── fr.php │ ├── getlang.php │ ├── id.php │ ├── it.php │ ├── jp.php │ ├── ko.php │ ├── languages.php │ ├── nl.php │ ├── pl.php │ ├── pt.php │ ├── pt_br.php │ ├── ru.php │ ├── sl.php │ ├── sr.php │ ├── sr_lat.php │ ├── tr.php │ ├── uk.php │ ├── vi.php │ ├── zh_cn.php │ └── zh_tw.php ├── inputvalidation.php ├── list_subscriptions.php ├── sort_options.php └── version.php ├── index.php ├── libs ├── OTPHP │ ├── Factory.php │ ├── FactoryInterface.php │ ├── HOTP.php │ ├── HOTPInterface.php │ ├── InternalClock.php │ ├── OTP.php │ ├── OTPInterface.php │ ├── ParameterTrait.php │ ├── TOTP.php │ ├── TOTPInterface.php │ └── Url.php ├── PHPMailer │ ├── Exception.php │ ├── PHPMailer.php │ └── SMTP.php ├── Psr │ └── Clock │ │ └── ClockInterface.php └── constant_time_encoding │ ├── Base32.php │ ├── Base32Hex.php │ ├── Base64.php │ ├── Base64DotSlash.php │ ├── Base64DotSlashOrdered.php │ ├── Base64UrlSafe.php │ ├── Binary.php │ ├── EncoderInterface.php │ ├── Encoding.php │ ├── Hex.php │ └── RFC4648.php ├── login.php ├── logos.php ├── logout.php ├── manifest.json ├── migrations ├── 000001.php ├── 000002.php ├── 000003.php ├── 000004.php ├── 000005.php ├── 000006.php ├── 000007.php ├── 000008.php ├── 000009.php ├── 000010.php ├── 000011.php ├── 000012.php ├── 000013.php ├── 000014.php ├── 000015.php ├── 000016.php ├── 000017.php ├── 000018.php ├── 000019.php ├── 000020.php ├── 000021.php ├── 000022.php ├── 000023.php ├── 000024.php ├── 000025.php ├── 000026.php ├── 000027.php ├── 000028.php ├── 000029.php ├── 000030.php ├── 000031.php ├── 000032.php ├── 000033.php ├── 000034.php ├── 000035.php └── 000036.php ├── nginx.conf ├── nginx.default.conf ├── passwordreset.php ├── profile.php ├── registration.php ├── screenshots ├── wallos-calendar.png ├── wallos-dashboard-dark.png ├── wallos-dashboard-light.png ├── wallos-dashboard-mobile-dark.png ├── wallos-dashboard-mobile-light.png ├── wallos-form.png └── wallos-stats.png ├── scripts ├── admin.js ├── all.js ├── calendar.js ├── common.js ├── dashboard.js ├── i18n │ ├── cs.js │ ├── da.js │ ├── de.js │ ├── el.js │ ├── en.js │ ├── es.js │ ├── fr.js │ ├── getlang.js │ ├── id.js │ ├── it.js │ ├── jp.js │ ├── ko.js │ ├── nl.js │ ├── pl.js │ ├── pt.js │ ├── pt_br.js │ ├── ru.js │ ├── sl.js │ ├── sr.js │ ├── sr_lat.js │ ├── tr.js │ ├── uk.js │ ├── vi.js │ ├── zh_cn.js │ └── zh_tw.js ├── libs │ ├── chart.js │ ├── qrcode.min.js │ └── sortable.min.js ├── login.js ├── notifications.js ├── profile.js ├── registration.js ├── settings.js ├── stats.js └── theme.js ├── service-worker.js ├── settings.php ├── startup.sh ├── stats.php ├── styles ├── barlow.css ├── brands.css ├── dark-theme.css ├── font-awesome.min.css ├── login-dark-theme.css ├── login.css ├── styles.css ├── theme.css └── themes │ ├── green.css │ ├── purple.css │ ├── red.css │ └── yellow.css ├── totp.php ├── verifyemail.php └── webfonts ├── fa-brands-400.ttf ├── fa-brands-400.woff2 ├── fa-regular-400.ttf ├── fa-regular-400.woff2 ├── fa-solid-900.ttf └── fa-solid-900.woff2 /.dockerignore: -------------------------------------------------------------------------------- 1 | # Exclude .vscode directory 2 | .vscode/ 3 | 4 | # Exclude .git directory 5 | .git/ -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ellite] 4 | custom: ['https://www.paypal.com/paypalme/miguelr'] 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /db/* 2 | !/db/wallos.empty.db 3 | /images/uploads/logos/* 4 | !/images/uploads/logos/wallos.png 5 | .DS_Store 6 | .idea/ 7 | .vscode/ 8 | -------------------------------------------------------------------------------- /.tmp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the php:8.2-fpm-alpine base image 2 | FROM php:8.2-fpm-alpine 3 | 4 | # Set working directory to /var/www/html 5 | WORKDIR /var/www/html 6 | 7 | # Update packages and install dependencies 8 | RUN apk upgrade --no-cache && \ 9 | apk add --no-cache shadow sqlite-dev libpng libpng-dev libjpeg-turbo libjpeg-turbo-dev freetype freetype-dev curl autoconf libgomp icu-dev icu-data-full nginx dcron tzdata imagemagick imagemagick-dev libzip-dev sqlite libwebp-dev && \ 10 | docker-php-ext-install pdo pdo_sqlite calendar && \ 11 | docker-php-ext-enable pdo pdo_sqlite && \ 12 | docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp && \ 13 | docker-php-ext-install -j$(nproc) gd intl zip && \ 14 | apk add --no-cache --virtual .build-deps $PHPIZE_DEPS && \ 15 | pecl install imagick && \ 16 | docker-php-ext-enable imagick && \ 17 | apk del .build-deps 18 | 19 | # Copy your PHP application files into the container 20 | COPY . . 21 | 22 | # Copy Nginx configuration 23 | COPY nginx.conf /etc/nginx/nginx.conf 24 | COPY nginx.default.conf /etc/nginx/http.d/default.conf 25 | 26 | # Copy the custom crontab file 27 | COPY cronjobs /etc/cron.d/cronjobs 28 | 29 | # Convert the line endings, allow read access to the cron file, and create cron log folder 30 | RUN dos2unix /etc/cron.d/cronjobs && \ 31 | chmod 0644 /etc/cron.d/cronjobs && \ 32 | /usr/bin/crontab /etc/cron.d/cronjobs && \ 33 | mkdir /var/log/cron && \ 34 | chown -R www-data:www-data /var/www/html && \ 35 | chmod +x /var/www/html/startup.sh && \ 36 | echo 'pm.max_children = 15' >> /usr/local/etc/php-fpm.d/zz-docker.conf && \ 37 | echo 'pm.max_requests = 500' >> /usr/local/etc/php-fpm.d/zz-docker.conf 38 | 39 | # Expose port 80 for Nginx 40 | EXPOSE 80 41 | 42 | ARG SOFTWARE_VERSION=1.20.0 43 | 44 | # Start both PHP-FPM, Nginx 45 | CMD ["sh", "-c", "/var/www/html/startup.sh"] 46 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | If you discover any security vulnerabilities in this project, please report them to the developer by emailing [wallos@henrique.pt](mailto:wallos@henrique.pt). I appreciate your help in keeping the project secure. 6 | 7 | ## Supported Versions 8 | 9 | This project is currently supported with security updates for the following versions: 10 | 11 | | Version | Supported | 12 | | ------- | ------------------ | 13 | | latest | :white_check_mark: | 14 | | main | :white_check_mark: | 15 | | 1.x.x | :x: | 16 | 17 | ## Security Measures 18 | 19 | I take security seriously and am working on ways to implement security measures to protect the project. 20 | 21 | What is being done currenty: 22 | - Periodically scan the docker image for vulnerabilities with trivy. 23 | 24 | ## Reporting a Security Concern 25 | 26 | If you have any security concerns or questions regarding the security of this project, please contact the developer at [wallos@henrique.pt](mailto:wallos@henrique.pt). 27 | 28 | ## Responsible Disclosure 29 | 30 | I kindly request that you follow responsible disclosure practices and give me reasonable time to address any reported vulnerabilities before making them public. 31 | 32 | -------------------------------------------------------------------------------- /cronjobs: -------------------------------------------------------------------------------- 1 | # Run the scripts every day 2 | 0 1 * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/updatenextpayment.php >> /var/log/cron/updatenextpayment.log 2>&1 3 | 0 2 * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/updateexchange.php >> /var/log/cron/updateexchange.log 2>&1 4 | 0 8 * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/sendcancellationnotifications.php >> /var/log/cron/sendcancellationnotifications.log 2>&1 5 | 0 9 * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/sendnotifications.php >> /var/log/cron/sendnotifications.log 2>&1 6 | */2 * * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/sendverificationemails.php >> /var/log/cron/sendverificationemails.log 2>&1 7 | */2 * * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/sendresetpasswordemails.php >> /var/log/cron/sendresetpasswordemails.log 2>&1 8 | 0 */6 * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/checkforupdates.php >> /var/log/cron/checkforupdates.log 2>&1 9 | 30 1 * * 1 /usr/local/bin/php /var/www/html/endpoints/cronjobs/storetotalyearlycost.php >> /var/log/cron/storetotalyearlycost.log 2>&1 -------------------------------------------------------------------------------- /db/wallos.empty.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/db/wallos.empty.db -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | wallos: 3 | container_name: wallos 4 | image: bellamy/wallos:latest 5 | ports: 6 | - "8282:80/tcp" 7 | environment: 8 | TZ: 'America/Toronto' 9 | # Volumes store your data between container upgrades 10 | volumes: 11 | - './db:/var/www/html/db' 12 | - './logos:/var/www/html/images/uploads/logos' 13 | restart: unless-stopped 14 | -------------------------------------------------------------------------------- /endpoints/admin/deleteunusedlogos.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | // Check that user is an admin 13 | if ($userId !== 1) { 14 | die(json_encode([ 15 | "success" => false, 16 | "message" => translate('error', $i18n) 17 | ])); 18 | } 19 | 20 | $query = 'SELECT logo FROM subscriptions'; 21 | $stmt = $db->prepare($query); 22 | $result = $stmt->execute(); 23 | 24 | $logosOnDB = []; 25 | while ($row = $result->fetchArray(SQLITE3_ASSOC)) { 26 | $logosOnDB[] = $row['logo']; 27 | } 28 | 29 | $logosOnDB = array_unique($logosOnDB); 30 | 31 | $uploadDir = '../../images/uploads/logos/'; 32 | $uploadFiles = scandir($uploadDir); 33 | 34 | foreach ($uploadFiles as $file) { 35 | if ($file != '.' && $file != '..' && $file != 'avatars') { 36 | $logosOnDisk[] = ['logo' => $file]; 37 | } 38 | } 39 | 40 | // Get all logos in the payment_methods table 41 | $query = 'SELECT icon FROM payment_methods'; 42 | $stmt = $db->prepare($query); 43 | $result = $stmt->execute(); 44 | 45 | while ($row = $result->fetchArray(SQLITE3_ASSOC)) { 46 | if (!strstr($row['icon'], "images/uploads/icons/")) { 47 | $logosOnDB[] = $row['icon']; 48 | } 49 | } 50 | 51 | $logosOnDB = array_unique($logosOnDB); 52 | 53 | // Find and delete unused logos 54 | $count = 0; 55 | foreach ($logosOnDisk as $disk) { 56 | foreach ($logosOnDB as $db) { 57 | $found = false; 58 | if ($disk['logo'] == $db) { 59 | $found = true; 60 | break; 61 | } 62 | } 63 | if (!$found) { 64 | unlink($uploadDir . $disk['logo']); 65 | $count++; 66 | } 67 | } 68 | 69 | echo json_encode([ 70 | "success" => true, 71 | "message" => translate('success', $i18n), 72 | 'count' => $count 73 | ]); 74 | 75 | 76 | ?> -------------------------------------------------------------------------------- /endpoints/admin/savesmtpsettings.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | // Check that user is an admin 13 | if ($userId !== 1) { 14 | die(json_encode([ 15 | "success" => false, 16 | "message" => translate('error', $i18n) 17 | ])); 18 | } 19 | 20 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 21 | 22 | $postData = file_get_contents("php://input"); 23 | $data = json_decode($postData, true); 24 | 25 | $smtpAddress = $data['smtpaddress']; 26 | $smtpPort = $data['smtpport']; 27 | $encryption = $data['encryption']; 28 | $smtpUsername = $data['smtpusername']; 29 | $smtpPassword = $data['smtppassword']; 30 | $fromEmail = $data['fromemail']; 31 | 32 | if (empty($smtpAddress) || empty($smtpPort)) { 33 | die(json_encode([ 34 | "success" => false, 35 | "message" => translate('fill_all_fields', $i18n) 36 | ])); 37 | } 38 | 39 | // Save settings 40 | $stmt = $db->prepare('UPDATE admin SET smtp_address = :smtp_address, smtp_port = :smtp_port, encryption = :encryption, smtp_username = :smtp_username, smtp_password = :smtp_password, from_email = :from_email'); 41 | $stmt->bindValue(':smtp_address', $smtpAddress, SQLITE3_TEXT); 42 | $stmt->bindValue(':smtp_port', $smtpPort, SQLITE3_TEXT); 43 | $encryption = empty($data['encryption']) ? 'tls' : $data['encryption']; 44 | $stmt->bindValue(':encryption', $encryption, SQLITE3_TEXT); 45 | $stmt->bindValue(':smtp_username', $smtpUsername, SQLITE3_TEXT); 46 | $stmt->bindValue(':smtp_password', $smtpPassword, SQLITE3_TEXT); 47 | $stmt->bindValue(':from_email', $fromEmail, SQLITE3_TEXT); 48 | $result = $stmt->execute(); 49 | 50 | if ($result) { 51 | die(json_encode([ 52 | "success" => true, 53 | "message" => translate('success', $i18n) 54 | ])); 55 | } else { 56 | die(json_encode([ 57 | "success" => false, 58 | "message" => translate('error', $i18n) 59 | ])); 60 | } 61 | 62 | } 63 | 64 | ?> -------------------------------------------------------------------------------- /endpoints/admin/updatenotification.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | // Check that user is an admin 13 | if ($userId !== 1) { 14 | die(json_encode([ 15 | "success" => false, 16 | "message" => translate('error', $i18n) 17 | ])); 18 | } 19 | 20 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 21 | 22 | $postData = file_get_contents("php://input"); 23 | $data = json_decode($postData, true); 24 | 25 | $updateNotification = $data['notificationEnabled']; 26 | 27 | // Save settings 28 | $stmt = $db->prepare('UPDATE admin SET update_notification = :update_notification'); 29 | $stmt->bindValue(':update_notification', $updateNotification, SQLITE3_INTEGER); 30 | $result = $stmt->execute(); 31 | 32 | if ($result) { 33 | die(json_encode([ 34 | "success" => true, 35 | "message" => translate('success', $i18n) 36 | ])); 37 | } else { 38 | die(json_encode([ 39 | "success" => false, 40 | "message" => translate('error', $i18n) 41 | ])); 42 | } 43 | 44 | } 45 | 46 | ?> -------------------------------------------------------------------------------- /endpoints/categories/sort.php: -------------------------------------------------------------------------------- 1 | prepare($sql); 12 | $stmt->bindParam(':order', $order, SQLITE3_INTEGER); 13 | $stmt->bindParam(':categoryId', $categoryId, SQLITE3_INTEGER); 14 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 15 | $result = $stmt->execute(); 16 | $order++; 17 | } 18 | 19 | $response = [ 20 | "success" => true, 21 | "message" => translate("sort_order_saved", $i18n) 22 | ]; 23 | echo json_encode($response); 24 | } else { 25 | $response = [ 26 | "success" => false, 27 | "errorMessage" => translate("session_expired", $i18n) 28 | ]; 29 | echo json_encode($response); 30 | die(); 31 | } 32 | 33 | ?> -------------------------------------------------------------------------------- /endpoints/cronjobs/checkforupdates.php: -------------------------------------------------------------------------------- 1 | [ 8 | 'header' => "User-Agent: Wallos\r\n" 9 | ] 10 | ]; 11 | 12 | $repository = 'ellite/Wallos'; // Change this to your repository if you fork Wallos 13 | $url = "https://api.github.com/repos/$repository/releases/latest"; 14 | 15 | $context = stream_context_create($options); 16 | $fetch = file_get_contents($url, false, $context); 17 | 18 | if ($fetch === false) { 19 | die('Error fetching data from GitHub API'); 20 | } 21 | 22 | $latestVersion = json_decode($fetch, true)['tag_name']; 23 | 24 | // Check that $latestVersion is a valid version number 25 | if (!preg_match('/^v\d+\.\d+\.\d+$/', $latestVersion)) { 26 | die('Error: Invalid version number from GitHub API'); 27 | } 28 | 29 | $db->exec("UPDATE admin SET latest_version = '$latestVersion'"); 30 | 31 | 32 | if (php_sapi_name() !== 'cli') { 33 | include __DIR__ . '/../../includes/version.php'; 34 | if (version_compare($latestVersion, $version) > 0) { 35 | echo "New version available: $latestVersion"; 36 | } else { 37 | echo "No new version available, currently on $version"; 38 | } 39 | } 40 | ?> -------------------------------------------------------------------------------- /endpoints/cronjobs/settimezone.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /endpoints/currency/add.php: -------------------------------------------------------------------------------- 1 | prepare($sqlInsert); 12 | $stmtInsert->bindParam(':name', $currencyName, SQLITE3_TEXT); 13 | $stmtInsert->bindParam(':symbol', $currencySymbol, SQLITE3_TEXT); 14 | $stmtInsert->bindParam(':code', $currencyCode, SQLITE3_TEXT); 15 | $stmtInsert->bindParam(':rate', $currencyRate, SQLITE3_TEXT); 16 | $stmtInsert->bindParam(':userId', $userId, SQLITE3_INTEGER); 17 | $resultInsert = $stmtInsert->execute(); 18 | 19 | if ($resultInsert) { 20 | $currencyId = $db->lastInsertRowID(); 21 | echo $currencyId; 22 | } else { 23 | echo translate('error_adding_currency', $i18n); 24 | } 25 | } else { 26 | $response = [ 27 | "success" => false, 28 | "message" => translate('session_expired', $i18n) 29 | ]; 30 | echo json_encode($response); 31 | } 32 | 33 | ?> -------------------------------------------------------------------------------- /endpoints/currency/edit.php: -------------------------------------------------------------------------------- 1 | prepare($sql); 13 | $stmt->bindParam(':name', $name, SQLITE3_TEXT); 14 | $stmt->bindParam(':symbol', $symbol, SQLITE3_TEXT); 15 | $stmt->bindParam(':code', $code, SQLITE3_TEXT); 16 | $stmt->bindParam(':currencyId', $currencyId, SQLITE3_INTEGER); 17 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 18 | $result = $stmt->execute(); 19 | 20 | if ($result) { 21 | $response = [ 22 | "success" => true, 23 | "message" => $name . " " . translate('currency_saved', $i18n) 24 | ]; 25 | echo json_encode($response); 26 | } else { 27 | $response = [ 28 | "success" => false, 29 | "message" => translate('failed_to_store_currency', $i18n) 30 | ]; 31 | echo json_encode($response); 32 | } 33 | } else { 34 | $response = [ 35 | "success" => false, 36 | "message" => translate('fields_missing', $i18n) 37 | ]; 38 | echo json_encode($response); 39 | } 40 | } else { 41 | $response = [ 42 | "success" => false, 43 | "message" => translate('session_expired', $i18n) 44 | ]; 45 | echo json_encode($response); 46 | } 47 | 48 | ?> -------------------------------------------------------------------------------- /endpoints/db/migrate.php: -------------------------------------------------------------------------------- 1 | query('SELECT name FROM sqlite_master WHERE type="table" AND name="migrations"') 24 | ->fetchArray(SQLITE3_ASSOC) !== false; 25 | 26 | if ($migrationTableExists) { 27 | $migrationQuery = $db->query('SELECT migration FROM migrations'); 28 | while ($row = $migrationQuery->fetchArray(SQLITE3_ASSOC)) { 29 | $completedMigrations[] = $row['migration']; 30 | } 31 | } 32 | 33 | $allMigrations = glob('migrations/*.php'); 34 | if (count($allMigrations) == 0) { 35 | $allMigrations = glob('../../migrations/*.php'); 36 | } 37 | 38 | $allMigrations = array_map(function ($migration) { 39 | return str_replace('../../', '', $migration); 40 | }, $allMigrations); 41 | 42 | $completedMigrations = array_map(function ($migration) { 43 | return str_replace('../../', '', $migration); 44 | }, $completedMigrations); 45 | 46 | $requiredMigrations = array_diff($allMigrations, $completedMigrations); 47 | 48 | if (count($requiredMigrations) === 0) { 49 | echo "No migrations to run.\n"; 50 | } 51 | 52 | foreach ($requiredMigrations as $migration) { 53 | if (!file_exists($migration)) { 54 | $migration = '../../' . $migration; 55 | } 56 | require_once $migration; 57 | 58 | $stmtInsert = $db->prepare('INSERT INTO migrations (migration) VALUES (:migration)'); 59 | $stmtInsert->bindParam(':migration', $migration, SQLITE3_TEXT); 60 | $stmtInsert->execute(); 61 | 62 | echo sprintf("Migration %s completed successfully.\n", $migration); 63 | } 64 | -------------------------------------------------------------------------------- /endpoints/payments/delete.php: -------------------------------------------------------------------------------- 1 | prepare($deleteQuery); 10 | $deleteStmt->bindParam(':paymentMethodId', $paymentMethodId, SQLITE3_INTEGER); 11 | $deleteStmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 12 | 13 | if ($deleteStmt->execute()) { 14 | $success['success'] = true; 15 | $success['message'] = translate('payment_method_removed', $i18n); 16 | $json = json_encode($success); 17 | header('Content-Type: application/json'); 18 | echo $json; 19 | } else { 20 | http_response_code(500); 21 | echo json_encode(array("message" => translate('error', $i18n))); 22 | } 23 | } else { 24 | http_response_code(405); 25 | echo json_encode(array("message" => translate('invalid_request_method', $i18n))); 26 | } 27 | } 28 | $db->close(); 29 | 30 | ?> -------------------------------------------------------------------------------- /endpoints/payments/payment.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if (!isset($_GET['paymentId']) || !isset($_GET['enabled'])) { 12 | die(json_encode([ 13 | "success" => false, 14 | "message" => translate('fields_missing', $i18n) 15 | ])); 16 | } 17 | 18 | $paymentId = $_GET['paymentId']; 19 | 20 | $stmt = $db->prepare('SELECT COUNT(*) as count FROM subscriptions WHERE payment_method_id=:paymentId and user_id=:userId'); 21 | $stmt->bindValue(':paymentId', $paymentId, SQLITE3_INTEGER); 22 | $stmt->bindValue(':userId', $userId, SQLITE3_INTEGER); 23 | $result = $stmt->execute(); 24 | $row = $result->fetchArray(); 25 | $inUse = $row['count'] === 1; 26 | 27 | if ($inUse) { 28 | die(json_encode([ 29 | "success" => false, 30 | "message" => translate('payment_in_use', $i18n) 31 | ])); 32 | } 33 | 34 | $enabled = $_GET['enabled']; 35 | 36 | $sqlUpdate = 'UPDATE payment_methods SET enabled=:enabled WHERE id=:id and user_id=:userId'; 37 | $stmtUpdate = $db->prepare($sqlUpdate); 38 | $stmtUpdate->bindParam(':enabled', $enabled); 39 | $stmtUpdate->bindParam(':id', $paymentId); 40 | $stmtUpdate->bindParam(':userId', $userId); 41 | $resultUpdate = $stmtUpdate->execute(); 42 | 43 | $text = $enabled ? "enabled" : "disabled"; 44 | 45 | if ($resultUpdate) { 46 | die(json_encode([ 47 | "success" => true, 48 | "message" => translate($text, $i18n) 49 | ])); 50 | } 51 | 52 | die(json_encode([ 53 | "success" => false, 54 | "message" => translate('failed_update_payment', $i18n) 55 | ])); 56 | -------------------------------------------------------------------------------- /endpoints/payments/rename.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | if (!isset($_POST['paymentId']) || !isset($_POST['name']) || $_POST['paymentId'] === '' || $_POST['name'] === '') { 13 | die(json_encode([ 14 | "success" => false, 15 | "message" => translate('fields_missing', $i18n) 16 | ])); 17 | } 18 | 19 | $paymentId = $_POST['paymentId']; 20 | $name = $_POST['name']; 21 | 22 | $sql = "UPDATE payment_methods SET name = :name WHERE id = :paymentId and user_id = :userId"; 23 | $stmt = $db->prepare($sql); 24 | $stmt->bindParam(':name', $name, SQLITE3_TEXT); 25 | $stmt->bindParam(':paymentId', $paymentId, SQLITE3_INTEGER); 26 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 27 | $result = $stmt->execute(); 28 | 29 | if ($result) { 30 | echo json_encode([ 31 | "success" => true, 32 | "message" => translate('payment_renamed', $i18n) 33 | ]); 34 | } else { 35 | echo json_encode([ 36 | "success" => false, 37 | "message" => translate('payment_not_renamed', $i18n) 38 | ]); 39 | } 40 | 41 | ?> -------------------------------------------------------------------------------- /endpoints/payments/sort.php: -------------------------------------------------------------------------------- 1 | prepare($sql); 12 | $stmt->bindParam(':order', $order, SQLITE3_INTEGER); 13 | $stmt->bindParam(':paymentMethodId', $paymentMethodId, SQLITE3_INTEGER); 14 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 15 | $result = $stmt->execute(); 16 | $order++; 17 | } 18 | 19 | $response = [ 20 | "success" => true, 21 | "message" => translate("sort_order_saved", $i18n) 22 | ]; 23 | echo json_encode($response); 24 | } else { 25 | $response = [ 26 | "success" => false, 27 | "errorMessage" => translate("session_expired", $i18n) 28 | ]; 29 | echo json_encode($response); 30 | die(); 31 | } 32 | 33 | ?> -------------------------------------------------------------------------------- /endpoints/settings/colortheme.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 13 | $postData = file_get_contents("php://input"); 14 | $data = json_decode($postData, true); 15 | 16 | $color = $data['color']; 17 | 18 | $stmt = $db->prepare('UPDATE settings SET color_theme = :color WHERE user_id = :userId'); 19 | $stmt->bindParam(':color', $color, SQLITE3_TEXT); 20 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 21 | 22 | if ($stmt->execute()) { 23 | die(json_encode([ 24 | "success" => true, 25 | "message" => translate("success", $i18n) 26 | ])); 27 | } else { 28 | die(json_encode([ 29 | "success" => false, 30 | "message" => translate("error", $i18n) 31 | ])); 32 | } 33 | } 34 | 35 | ?> -------------------------------------------------------------------------------- /endpoints/settings/convert_currency.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 12 | $postData = file_get_contents("php://input"); 13 | $data = json_decode($postData, true); 14 | 15 | $convert_currency = $data['value']; 16 | 17 | $stmt = $db->prepare('UPDATE settings SET convert_currency = :convert_currency WHERE user_id = :userId'); 18 | $stmt->bindParam(':convert_currency', $convert_currency, SQLITE3_INTEGER); 19 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 20 | 21 | if ($stmt->execute()) { 22 | die(json_encode([ 23 | "success" => true, 24 | "message" => translate("success", $i18n) 25 | ])); 26 | } else { 27 | die(json_encode([ 28 | "success" => false, 29 | "message" => translate("error", $i18n) 30 | ])); 31 | } 32 | } 33 | 34 | ?> -------------------------------------------------------------------------------- /endpoints/settings/customcss.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 13 | $postData = file_get_contents("php://input"); 14 | $data = json_decode($postData, true); 15 | 16 | $customCss = $data['customCss']; 17 | 18 | $stmt = $db->prepare('DELETE FROM custom_css_style WHERE user_id = :userId'); 19 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 20 | $stmt->execute(); 21 | 22 | $stmt = $db->prepare('INSERT INTO custom_css_style (css, user_id) VALUES (:customCss, :userId)'); 23 | $stmt->bindParam(':customCss', $customCss, SQLITE3_TEXT); 24 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 25 | 26 | if ($stmt->execute()) { 27 | die(json_encode([ 28 | "success" => true, 29 | "message" => translate("success", $i18n) 30 | ])); 31 | } else { 32 | die(json_encode([ 33 | "success" => false, 34 | "message" => translate("error", $i18n) 35 | ])); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /endpoints/settings/customtheme.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 13 | $postData = file_get_contents("php://input"); 14 | $data = json_decode($postData, true); 15 | 16 | $main_color = $data['mainColor']; 17 | $accent_color = $data['accentColor']; 18 | $hover_color = $data['hoverColor']; 19 | 20 | if ($main_color == $accent_color) { 21 | die(json_encode([ 22 | "success" => false, 23 | "message" => translate("main_accent_color_error", $i18n) 24 | ])); 25 | } 26 | 27 | $stmt = $db->prepare('DELETE FROM custom_colors WHERE user_id = :userId'); 28 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 29 | $stmt->execute(); 30 | 31 | $stmt = $db->prepare('INSERT INTO custom_colors (main_color, accent_color, hover_color, user_id) VALUES (:main_color, :accent_color, :hover_color, :userId)'); 32 | $stmt->bindParam(':main_color', $main_color, SQLITE3_TEXT); 33 | $stmt->bindParam(':accent_color', $accent_color, SQLITE3_TEXT); 34 | $stmt->bindParam(':hover_color', $hover_color, SQLITE3_TEXT); 35 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 36 | 37 | if ($stmt->execute()) { 38 | die(json_encode([ 39 | "success" => true, 40 | "message" => translate("success", $i18n) 41 | ])); 42 | } else { 43 | die(json_encode([ 44 | "success" => false, 45 | "message" => translate("error", $i18n) 46 | ])); 47 | } 48 | } 49 | 50 | ?> -------------------------------------------------------------------------------- /endpoints/settings/disabled_to_bottom.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 12 | $postData = file_get_contents("php://input"); 13 | $data = json_decode($postData, true); 14 | 15 | $disabled_to_bottom = $data['value']; 16 | 17 | $stmt = $db->prepare('UPDATE settings SET disabled_to_bottom = :disabled_to_bottom WHERE user_id = :userId'); 18 | $stmt->bindParam(':disabled_to_bottom', $disabled_to_bottom, SQLITE3_INTEGER); 19 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 20 | 21 | if ($stmt->execute()) { 22 | die(json_encode([ 23 | "success" => true, 24 | "message" => translate("success", $i18n) 25 | ])); 26 | } else { 27 | die(json_encode([ 28 | "success" => false, 29 | "message" => translate("error", $i18n) 30 | ])); 31 | } 32 | } 33 | 34 | ?> -------------------------------------------------------------------------------- /endpoints/settings/hide_disabled.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 12 | $postData = file_get_contents("php://input"); 13 | $data = json_decode($postData, true); 14 | 15 | $hide_disabled = $data['value']; 16 | 17 | $stmt = $db->prepare('UPDATE settings SET hide_disabled = :hide_disabled WHERE user_id = :userId'); 18 | $stmt->bindParam(':hide_disabled', $hide_disabled, SQLITE3_INTEGER); 19 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 20 | 21 | if ($stmt->execute()) { 22 | die(json_encode([ 23 | "success" => true, 24 | "message" => translate("success", $i18n) 25 | ])); 26 | } else { 27 | die(json_encode([ 28 | "success" => false, 29 | "message" => translate("error", $i18n) 30 | ])); 31 | } 32 | } 33 | 34 | ?> -------------------------------------------------------------------------------- /endpoints/settings/mobile_navigation.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 13 | $postData = file_get_contents("php://input"); 14 | $data = json_decode($postData, true); 15 | 16 | $mobile_nav = $data['value']; 17 | 18 | $stmt = $db->prepare('UPDATE settings SET mobile_nav = :mobile_nav WHERE user_id = :userId'); 19 | $stmt->bindParam(':mobile_nav', $mobile_nav, SQLITE3_INTEGER); 20 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 21 | 22 | if ($stmt->execute()) { 23 | die(json_encode([ 24 | "success" => true, 25 | "message" => translate("success", $i18n) 26 | ])); 27 | } else { 28 | die(json_encode([ 29 | "success" => false, 30 | "message" => translate("error", $i18n) 31 | ])); 32 | } 33 | } 34 | « 35 | 36 | ?> -------------------------------------------------------------------------------- /endpoints/settings/monthly_price.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 12 | $postData = file_get_contents("php://input"); 13 | $data = json_decode($postData, true); 14 | 15 | $monthly_price = $data['value']; 16 | 17 | $stmt = $db->prepare('UPDATE settings SET monthly_price = :monthly_price WHERE user_id = :userId'); 18 | $stmt->bindParam(':monthly_price', $monthly_price, SQLITE3_INTEGER); 19 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 20 | 21 | if ($stmt->execute()) { 22 | die(json_encode([ 23 | "success" => true, 24 | "message" => translate("success", $i18n) 25 | ])); 26 | } else { 27 | die(json_encode([ 28 | "success" => false, 29 | "message" => translate("error", $i18n) 30 | ])); 31 | } 32 | } 33 | 34 | ?> -------------------------------------------------------------------------------- /endpoints/settings/remove_background.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 12 | $postData = file_get_contents("php://input"); 13 | $data = json_decode($postData, true); 14 | 15 | $remove_background = $data['value']; 16 | 17 | $stmt = $db->prepare('UPDATE settings SET remove_background = :remove_background WHERE user_id = :userId'); 18 | $stmt->bindParam(':remove_background', $remove_background, SQLITE3_INTEGER); 19 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 20 | 21 | if ($stmt->execute()) { 22 | die(json_encode([ 23 | "success" => true, 24 | "message" => translate("success", $i18n) 25 | ])); 26 | } else { 27 | die(json_encode([ 28 | "success" => false, 29 | "message" => translate("error", $i18n) 30 | ])); 31 | } 32 | } 33 | 34 | ?> -------------------------------------------------------------------------------- /endpoints/settings/resettheme.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | if ($_SERVER["REQUEST_METHOD"] === "DELETE") { 13 | $stmt = $db->prepare('DELETE FROM custom_colors WHERE user_id = :userId'); 14 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 15 | 16 | if ($stmt->execute()) { 17 | die(json_encode([ 18 | "success" => true, 19 | "message" => translate("success", $i18n) 20 | ])); 21 | } else { 22 | die(json_encode([ 23 | "success" => false, 24 | "message" => translate("error", $i18n) 25 | ])); 26 | } 27 | } 28 | 29 | ?> -------------------------------------------------------------------------------- /endpoints/settings/show_original_price.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 12 | $postData = file_get_contents("php://input"); 13 | $data = json_decode($postData, true); 14 | 15 | $show_original_price = $data['value']; 16 | 17 | $stmt = $db->prepare('UPDATE settings SET show_original_price = :show_original_price WHERE user_id = :userId'); 18 | $stmt->bindParam(':show_original_price', $show_original_price, SQLITE3_INTEGER); 19 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 20 | 21 | if ($stmt->execute()) { 22 | die(json_encode([ 23 | "success" => true, 24 | "message" => translate("success", $i18n) 25 | ])); 26 | } else { 27 | die(json_encode([ 28 | "success" => false, 29 | "message" => translate("error", $i18n) 30 | ])); 31 | } 32 | } 33 | 34 | ?> -------------------------------------------------------------------------------- /endpoints/settings/subscription_progress.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 12 | $postData = file_get_contents("php://input"); 13 | $data = json_decode($postData, true); 14 | 15 | $show_subscription_progress = $data['value']; 16 | 17 | $stmt = $db->prepare('UPDATE settings SET show_subscription_progress = :show_subscription_progress WHERE user_id = :userId'); 18 | $stmt->bindParam(':show_subscription_progress', $show_subscription_progress, SQLITE3_INTEGER); 19 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 20 | 21 | if ($stmt->execute()) { 22 | die(json_encode([ 23 | "success" => true, 24 | "message" => translate("success", $i18n) 25 | ])); 26 | } else { 27 | die(json_encode([ 28 | "success" => false, 29 | "message" => translate("error", $i18n) 30 | ])); 31 | } 32 | } 33 | 34 | ?> -------------------------------------------------------------------------------- /endpoints/settings/theme.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 12 | $postData = file_get_contents("php://input"); 13 | $data = json_decode($postData, true); 14 | 15 | $theme = $data['theme']; 16 | 17 | $stmt = $db->prepare('UPDATE settings SET dark_theme = :theme WHERE user_id = :userId'); 18 | $stmt->bindParam(':theme', $theme, SQLITE3_INTEGER); 19 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 20 | 21 | if ($stmt->execute()) { 22 | die(json_encode([ 23 | "success" => true, 24 | "message" => translate("success", $i18n) 25 | ])); 26 | } else { 27 | die(json_encode([ 28 | "success" => false, 29 | "message" => translate("error", $i18n) 30 | ])); 31 | } 32 | } 33 | 34 | ?> -------------------------------------------------------------------------------- /endpoints/subscription/delete.php: -------------------------------------------------------------------------------- 1 | prepare($deleteQuery); 9 | $deleteStmt->bindParam(':subscriptionId', $subscriptionId, SQLITE3_INTEGER); 10 | $deleteStmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 11 | 12 | if ($deleteStmt->execute()) { 13 | $query = "UPDATE subscriptions SET replacement_subscription_id = NULL WHERE replacement_subscription_id = :subscriptionId AND user_id = :userId"; 14 | $stmt = $db->prepare($query); 15 | $stmt->bindParam(':subscriptionId', $subscriptionId, SQLITE3_INTEGER); 16 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 17 | $stmt->execute(); 18 | 19 | http_response_code(204); 20 | } else { 21 | http_response_code(500); 22 | echo json_encode(array("message" => translate('error_deleting_subscription', $i18n))); 23 | } 24 | } else { 25 | http_response_code(405); 26 | echo json_encode(array("message" => translate('invalid_request_method', $i18n))); 27 | } 28 | } 29 | $db->close(); 30 | ?> -------------------------------------------------------------------------------- /endpoints/subscription/getcalendar.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 13 | $postData = file_get_contents("php://input"); 14 | $data = json_decode($postData, true); 15 | 16 | $id = $data['id']; 17 | 18 | $stmt = $db->prepare('SELECT * FROM subscriptions WHERE id = :id AND user_id = :userId'); 19 | $stmt->bindParam(':id', $id, SQLITE3_INTEGER); 20 | $stmt->bindParam(':userId', $_SESSION['userId'], SQLITE3_INTEGER); // Assuming $_SESSION['userId'] holds the logged-in user's ID 21 | $result = $stmt->execute(); 22 | 23 | if ($result === false) { 24 | die(json_encode([ 25 | 'success' => false, 26 | 'message' => "Subscription not found" 27 | ])); 28 | } 29 | 30 | $subscription = $result->fetchArray(SQLITE3_ASSOC); // Fetch the subscription details as an associative array 31 | 32 | if ($subscription) { 33 | // get payer name from household object 34 | $subscription['payer_user'] = $members[$subscription['payer_user_id']]['name']; 35 | $subscription['category'] = $categories[$subscription['category_id']]['name']; 36 | $subscription['payment_method'] = $payment_methods[$subscription['payment_method_id']]['name']; 37 | $subscription['currency'] = $currencies[$subscription['currency_id']]['symbol']; 38 | $subscription['price'] = number_format($subscription['price'], 2); 39 | 40 | echo json_encode([ 41 | 'success' => true, 42 | 'data' => $subscription 43 | ]); 44 | } else { 45 | echo json_encode([ 46 | 'success' => false, 47 | 'message' => "Subscription not found" 48 | ]); 49 | } 50 | } 51 | ?> -------------------------------------------------------------------------------- /endpoints/subscriptions/export.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | require_once '../../includes/getdbkeys.php'; 12 | 13 | $subscriptions = array(); 14 | 15 | $query = "SELECT * FROM subscriptions WHERE user_id = :userId"; 16 | $stmt = $db->prepare($query); 17 | $stmt->bindValue(':userId', $userId, SQLITE3_INTEGER); 18 | $result = $stmt->execute(); 19 | 20 | while ($row = $result->fetchArray(SQLITE3_ASSOC)) { 21 | $cycle = $cycles[$row['cycle']]['name']; 22 | $frequency =$row['frequency']; 23 | 24 | $cyclesMap = array( 25 | 'Daily' => 'Days', 26 | 'Weekly' => 'Weeks', 27 | 'Monthly' => 'Months', 28 | 'Yearly' => 'Years' 29 | ); 30 | 31 | if ($frequency == 1) { 32 | $cyclePrint = $cycle; 33 | } else { 34 | $cyclePrint = "Every " . $frequency . " " . $cyclesMap[$cycle]; 35 | } 36 | 37 | $subscriptionDetails = array( 38 | 'Name' => str_replace(',', ' ', $row['name']), 39 | 'Payment Cycle' => $cyclePrint, 40 | 'Next Payment' => $row['next_payment'], 41 | 'Renewal' => $row['auto_renew'] ? 'Automatic' : 'Manual', 42 | 'Category' => str_replace(',', ' ', $categories[$row['category_id']]['name']), 43 | 'Payment Method' => str_replace(',', ' ', $payment_methods[$row['payment_method_id']]['name']), 44 | 'Paid By' => str_replace(',', ' ', $members[$row['payer_user_id']]['name']), 45 | 'Price' => $currencies[$row['currency_id']]['symbol'] . $row['price'], 46 | 'Notes' => str_replace(',', ' ', $row['notes']), 47 | 'URL' => $row['url'], 48 | 'State' => $row['inactive'] ? 'Disabled' : 'Enabled', 49 | 'Notifications' => $row['notify'] ? 'Enabled' : 'Disabled', 50 | 'Cancellation Date' => $row['cancellation_date'], 51 | 'Active' => $row['inactive'] ? 'No' : 'Yes', 52 | ); 53 | 54 | $subscriptions[] = $subscriptionDetails; 55 | } 56 | 57 | die(json_encode([ 58 | "success" => true, 59 | "subscriptions" => $subscriptions 60 | ])); 61 | 62 | 63 | ?> 64 | -------------------------------------------------------------------------------- /endpoints/user/budget.php: -------------------------------------------------------------------------------- 1 | false, 9 | "message" => translate('session_expired', $i18n) 10 | ])); 11 | } 12 | 13 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 14 | $postData = file_get_contents("php://input"); 15 | $data = json_decode($postData, true); 16 | 17 | $budget = $data["budget"]; 18 | 19 | $sql = "UPDATE user SET budget = :budget WHERE id = :userId"; 20 | $stmt = $db->prepare($sql); 21 | $stmt->bindValue(':budget', $budget, SQLITE3_TEXT); 22 | $stmt->bindValue(':userId', $userId, SQLITE3_TEXT); 23 | $result = $stmt->execute(); 24 | 25 | if ($result) { 26 | $response = [ 27 | "success" => true, 28 | "message" => translate('user_details_saved', $i18n) 29 | ]; 30 | echo json_encode($response); 31 | } else { 32 | $response = [ 33 | "success" => false, 34 | "message" => translate('error_updating_user_data', $i18n) 35 | ]; 36 | echo json_encode($response); 37 | } 38 | } 39 | 40 | 41 | ?> -------------------------------------------------------------------------------- /endpoints/user/delete_avatar.php: -------------------------------------------------------------------------------- 1 | false, 8 | "message" => translate('session_expired', $i18n) 9 | ])); 10 | } 11 | 12 | $input = json_decode(file_get_contents('php://input'), true); 13 | if (isset($input['avatar'])) { 14 | $baseDir = realpath("../../images/uploads/logos/avatars/"); 15 | $avatar = $input['avatar']; 16 | 17 | $cleanAvatar = rawurldecode($avatar); 18 | $cleanAvatar = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', $cleanAvatar); 19 | 20 | $filePath = realpath($baseDir . DIRECTORY_SEPARATOR . $cleanAvatar); 21 | 22 | if ($filePath === false || strpos($filePath, $baseDir) !== 0) { 23 | echo json_encode([ 24 | "success" => false, 25 | "message" => "Invalid file path" 26 | ]); 27 | exit; 28 | } 29 | 30 | $sql = "SELECT avatar FROM user WHERE id = :userId"; 31 | $stmt = $db->prepare($sql); 32 | $stmt->bindValue(':userId', $userId, SQLITE3_INTEGER); 33 | $result = $stmt->execute(); 34 | $userAvatar = $result->fetchArray(SQLITE3_ASSOC)['avatar']; 35 | 36 | // Check if $avatar matches the avatar in the user table 37 | if ($avatar === $userAvatar) { 38 | echo json_encode(array("success" => false, "message" => "Avatar in use")); 39 | } else { 40 | if (file_exists($filePath)) { 41 | unlink($filePath); 42 | echo json_encode(array("success" => true, "message" => translate("success", $i18n))); 43 | } else { 44 | echo json_encode(array("success" => false, "message" => translate("error", $i18n))); 45 | } 46 | } 47 | } else { 48 | echo json_encode(array("success" => false, "message" => translate("error", $i18n))); 49 | } 50 | 51 | ?> -------------------------------------------------------------------------------- /endpoints/user/regenerateapikey.php: -------------------------------------------------------------------------------- 1 | false, 7 | "message" => translate('session_expired', $i18n) 8 | ])); 9 | } 10 | 11 | if ($_SERVER["REQUEST_METHOD"] === "POST") { 12 | $postData = file_get_contents("php://input"); 13 | $data = json_decode($postData, true); 14 | 15 | $apiKey = bin2hex(random_bytes(32)); 16 | 17 | $sql = "UPDATE user SET api_key = :apiKey WHERE id = :userId"; 18 | $stmt = $db->prepare($sql); 19 | $stmt->bindValue(':apiKey', $apiKey, SQLITE3_TEXT); 20 | $stmt->bindValue(':userId', $userId, SQLITE3_TEXT); 21 | $result = $stmt->execute(); 22 | 23 | if ($result) { 24 | $response = [ 25 | "success" => true, 26 | "message" => translate('user_details_saved', $i18n), 27 | "apiKey" => $apiKey 28 | ]; 29 | echo json_encode($response); 30 | } else { 31 | $response = [ 32 | "success" => false, 33 | "message" => translate('error_updating_user_data', $i18n) 34 | ]; 35 | echo json_encode($response); 36 | } 37 | 38 | } 39 | 40 | ?> -------------------------------------------------------------------------------- /images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/Thumbs.db -------------------------------------------------------------------------------- /images/avatars/0.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/avatars/1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/avatars/2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/avatars/3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/avatars/4.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/avatars/5.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/avatars/6.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/avatars/7.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/avatars/8.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/avatars/9.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/icon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/android-chrome-192x192.png -------------------------------------------------------------------------------- /images/icon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/android-chrome-512x512.png -------------------------------------------------------------------------------- /images/icon/apple-touch-icon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/apple-touch-icon-152.png -------------------------------------------------------------------------------- /images/icon/apple-touch-icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/apple-touch-icon-180.png -------------------------------------------------------------------------------- /images/icon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/apple-touch-icon.png -------------------------------------------------------------------------------- /images/icon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/favicon-16x16.png -------------------------------------------------------------------------------- /images/icon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/favicon-32x32.png -------------------------------------------------------------------------------- /images/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/favicon.ico -------------------------------------------------------------------------------- /images/icon/maskable_icon_x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/maskable_icon_x192.png -------------------------------------------------------------------------------- /images/icon/maskable_icon_x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/icon/maskable_icon_x512.png -------------------------------------------------------------------------------- /images/screenshots/desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/screenshots/desktop.png -------------------------------------------------------------------------------- /images/screenshots/mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/screenshots/mobile.png -------------------------------------------------------------------------------- /images/siteicons/payments/Amex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Amex.png -------------------------------------------------------------------------------- /images/siteicons/payments/ApplePay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/ApplePay.png -------------------------------------------------------------------------------- /images/siteicons/payments/Bitcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Bitcoin.png -------------------------------------------------------------------------------- /images/siteicons/payments/BitcoinCash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/BitcoinCash.png -------------------------------------------------------------------------------- /images/siteicons/payments/DinersClub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/DinersClub.png -------------------------------------------------------------------------------- /images/siteicons/payments/Discover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Discover.png -------------------------------------------------------------------------------- /images/siteicons/payments/Etherium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Etherium.png -------------------------------------------------------------------------------- /images/siteicons/payments/Forbrugsforeningen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Forbrugsforeningen.png -------------------------------------------------------------------------------- /images/siteicons/payments/GooglePay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/GooglePay.png -------------------------------------------------------------------------------- /images/siteicons/payments/Interac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Interac.png -------------------------------------------------------------------------------- /images/siteicons/payments/JCB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/JCB.png -------------------------------------------------------------------------------- /images/siteicons/payments/Klarna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Klarna.png -------------------------------------------------------------------------------- /images/siteicons/payments/Lightcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Lightcoin.png -------------------------------------------------------------------------------- /images/siteicons/payments/Maestro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Maestro.png -------------------------------------------------------------------------------- /images/siteicons/payments/Mastercard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Mastercard.png -------------------------------------------------------------------------------- /images/siteicons/payments/PayPal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/PayPal.png -------------------------------------------------------------------------------- /images/siteicons/payments/Payoneer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Payoneer.png -------------------------------------------------------------------------------- /images/siteicons/payments/Stripe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Stripe.png -------------------------------------------------------------------------------- /images/siteicons/payments/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Thumbs.db -------------------------------------------------------------------------------- /images/siteicons/payments/Visa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Visa.png -------------------------------------------------------------------------------- /images/siteicons/payments/Yandex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/Yandex.png -------------------------------------------------------------------------------- /images/siteicons/payments/affirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/affirm.png -------------------------------------------------------------------------------- /images/siteicons/payments/alipay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/alipay.png -------------------------------------------------------------------------------- /images/siteicons/payments/amazonpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/amazonpay.png -------------------------------------------------------------------------------- /images/siteicons/payments/bancontact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/bancontact.png -------------------------------------------------------------------------------- /images/siteicons/payments/bitpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/bitpay.png -------------------------------------------------------------------------------- /images/siteicons/payments/citadele.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/citadele.png -------------------------------------------------------------------------------- /images/siteicons/payments/directdebit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/directdebit.png -------------------------------------------------------------------------------- /images/siteicons/payments/elo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/elo.png -------------------------------------------------------------------------------- /images/siteicons/payments/facebookpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/facebookpay.png -------------------------------------------------------------------------------- /images/siteicons/payments/gitopay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/gitopay.png -------------------------------------------------------------------------------- /images/siteicons/payments/ideal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/ideal.png -------------------------------------------------------------------------------- /images/siteicons/payments/paysafe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/paysafe.png -------------------------------------------------------------------------------- /images/siteicons/payments/poli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/poli.png -------------------------------------------------------------------------------- /images/siteicons/payments/qiwi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/qiwi.png -------------------------------------------------------------------------------- /images/siteicons/payments/samsungpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/samsungpay.png -------------------------------------------------------------------------------- /images/siteicons/payments/shoppay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/shoppay.png -------------------------------------------------------------------------------- /images/siteicons/payments/skrill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/skrill.png -------------------------------------------------------------------------------- /images/siteicons/payments/sofort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/sofort.png -------------------------------------------------------------------------------- /images/siteicons/payments/unionpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/unionpay.png -------------------------------------------------------------------------------- /images/siteicons/payments/venmo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/venmo.png -------------------------------------------------------------------------------- /images/siteicons/payments/verifone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/verifone.png -------------------------------------------------------------------------------- /images/siteicons/payments/webmoney.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/webmoney.png -------------------------------------------------------------------------------- /images/siteicons/payments/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/payments/wechat.png -------------------------------------------------------------------------------- /images/siteicons/pwa/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/pwa/about.png -------------------------------------------------------------------------------- /images/siteicons/pwa/calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/pwa/calendar.png -------------------------------------------------------------------------------- /images/siteicons/pwa/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/pwa/settings.png -------------------------------------------------------------------------------- /images/siteicons/pwa/stats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/pwa/stats.png -------------------------------------------------------------------------------- /images/siteicons/pwa/subscriptions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/pwa/subscriptions.png -------------------------------------------------------------------------------- /images/siteicons/svg/automatic.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/siteicons/svg/category.php: -------------------------------------------------------------------------------- 1 | 2 | Page Setting Streamline Icon: https://streamlinehq.com 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/siteicons/svg/check.php: -------------------------------------------------------------------------------- 1 | 5 | Check Thick Streamline Icon: https://streamlinehq.com 6 | 7 | 8 | 9 | '; 10 | ?> -------------------------------------------------------------------------------- /images/siteicons/svg/clone.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/siteicons/svg/delete.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /images/siteicons/svg/edit.php: -------------------------------------------------------------------------------- 1 | 2 | Pencil Square Streamline Icon: https://streamlinehq.com 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /images/siteicons/svg/export_ical.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /images/siteicons/svg/mobile-menu/about.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/siteicons/svg/mobile-menu/calendar.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/siteicons/svg/mobile-menu/delete.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/siteicons/svg/mobile-menu/edit.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/siteicons/svg/mobile-menu/home.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/siteicons/svg/mobile-menu/logout.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/siteicons/svg/mobile-menu/renew.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/siteicons/svg/mobile-menu/statistics.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /images/siteicons/svg/notes.php: -------------------------------------------------------------------------------- 1 | 2 | Notepad Text Streamline Icon: https://streamlinehq.com 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /images/siteicons/svg/renew.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /images/siteicons/svg/save.php: -------------------------------------------------------------------------------- 1 | 2 | File Check Alternate Streamline Icon: https://streamlinehq.com 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/siteicons/svg/subscription.php: -------------------------------------------------------------------------------- 1 | 2 | Layers 1 Streamline Icon: https://streamlinehq.com 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/siteicons/svg/web.php: -------------------------------------------------------------------------------- 1 | 2 | Web Streamline Icon: https://streamlinehq.com 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/siteicons/svg/websearch.php: -------------------------------------------------------------------------------- 1 | 2 | Search Visual Streamline Icon: https://streamlinehq.com 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/siteicons/wallos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/wallos.png -------------------------------------------------------------------------------- /images/siteicons/walloswhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteicons/walloswhite.png -------------------------------------------------------------------------------- /images/siteimages/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteimages/Thumbs.db -------------------------------------------------------------------------------- /images/siteimages/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteimages/empty.png -------------------------------------------------------------------------------- /images/siteimages/emptydark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteimages/emptydark.png -------------------------------------------------------------------------------- /images/siteimages/mobilenav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteimages/mobilenav.png -------------------------------------------------------------------------------- /images/siteimages/mobilenavdark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/siteimages/mobilenavdark.png -------------------------------------------------------------------------------- /images/uploads/icons/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/Thumbs.db -------------------------------------------------------------------------------- /images/uploads/icons/affirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/affirm.png -------------------------------------------------------------------------------- /images/uploads/icons/alipay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/alipay.png -------------------------------------------------------------------------------- /images/uploads/icons/amazonpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/amazonpay.png -------------------------------------------------------------------------------- /images/uploads/icons/applepay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/applepay.png -------------------------------------------------------------------------------- /images/uploads/icons/banktransfer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/banktransfer.png -------------------------------------------------------------------------------- /images/uploads/icons/creditcard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/creditcard.png -------------------------------------------------------------------------------- /images/uploads/icons/crypto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/crypto.png -------------------------------------------------------------------------------- /images/uploads/icons/directdebit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/directdebit.png -------------------------------------------------------------------------------- /images/uploads/icons/elo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/elo.png -------------------------------------------------------------------------------- /images/uploads/icons/facebookpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/facebookpay.png -------------------------------------------------------------------------------- /images/uploads/icons/giropay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/giropay.png -------------------------------------------------------------------------------- /images/uploads/icons/googlepay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/googlepay.png -------------------------------------------------------------------------------- /images/uploads/icons/ideal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/ideal.png -------------------------------------------------------------------------------- /images/uploads/icons/interac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/interac.png -------------------------------------------------------------------------------- /images/uploads/icons/klarna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/klarna.png -------------------------------------------------------------------------------- /images/uploads/icons/money.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/money.png -------------------------------------------------------------------------------- /images/uploads/icons/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/paypal.png -------------------------------------------------------------------------------- /images/uploads/icons/paysafe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/paysafe.png -------------------------------------------------------------------------------- /images/uploads/icons/poli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/poli.png -------------------------------------------------------------------------------- /images/uploads/icons/qiwi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/qiwi.png -------------------------------------------------------------------------------- /images/uploads/icons/samsungpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/samsungpay.png -------------------------------------------------------------------------------- /images/uploads/icons/sepa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/sepa.png -------------------------------------------------------------------------------- /images/uploads/icons/shoppay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/shoppay.png -------------------------------------------------------------------------------- /images/uploads/icons/skrill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/skrill.png -------------------------------------------------------------------------------- /images/uploads/icons/sofort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/sofort.png -------------------------------------------------------------------------------- /images/uploads/icons/stripe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/stripe.png -------------------------------------------------------------------------------- /images/uploads/icons/unionpay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/unionpay.png -------------------------------------------------------------------------------- /images/uploads/icons/venmo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/venmo.png -------------------------------------------------------------------------------- /images/uploads/icons/verifone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/verifone.png -------------------------------------------------------------------------------- /images/uploads/icons/webmoney.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/webmoney.png -------------------------------------------------------------------------------- /images/uploads/icons/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/uploads/icons/wechat.png -------------------------------------------------------------------------------- /images/wallossolid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/wallossolid.png -------------------------------------------------------------------------------- /images/wallossolidwhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/images/wallossolidwhite.png -------------------------------------------------------------------------------- /includes/checkuser.php: -------------------------------------------------------------------------------- 1 | query($query); 4 | $row = $result->fetchArray(SQLITE3_ASSOC); 5 | $userCount = $row['count']; 6 | ?> -------------------------------------------------------------------------------- /includes/connect.php: -------------------------------------------------------------------------------- 1 | busyTimeout(5000); 7 | 8 | if (!$db) { 9 | die('Connection to the database failed.'); 10 | } 11 | 12 | ?> -------------------------------------------------------------------------------- /includes/connect_endpoint.php: -------------------------------------------------------------------------------- 1 | busyTimeout(5000); 6 | 7 | if (!$db) { 8 | die('Connection to the database failed.'); 9 | } 10 | 11 | require_once 'i18n/languages.php'; 12 | require_once 'i18n/getlang.php'; 13 | require_once 'i18n/' . $lang . '.php'; 14 | 15 | session_start(); 16 | 17 | if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) { 18 | $userId = $_SESSION['userId']; 19 | } else { 20 | $userId = 0; 21 | } 22 | 23 | ?> -------------------------------------------------------------------------------- /includes/connect_endpoint_crontabs.php: -------------------------------------------------------------------------------- 1 | busyTimeout(5000); 6 | 7 | if (!$db) { 8 | die('Connection to the database failed.'); 9 | } 10 | 11 | require_once __DIR__ . '/../includes/i18n/languages.php'; 12 | require_once __DIR__ . '/../includes/i18n/getlang.php'; 13 | require_once __DIR__ . '/../includes/i18n/' . $lang . '.php'; 14 | 15 | ?> -------------------------------------------------------------------------------- /includes/currency_formatter.php: -------------------------------------------------------------------------------- 1 | formatCurrency($amount, $currency); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /includes/footer.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | 6 |
7 | 8 | 9 |
10 |
11 | 12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 | 20 | 21 |
22 |
23 | 24 |
25 |
26 | 27 | close(); 30 | } 31 | ?> 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /includes/getdbkeys.php: -------------------------------------------------------------------------------- 1 | prepare($query); 6 | $stmt->bindValue(':userId', $userId, SQLITE3_INTEGER); 7 | $result = $stmt->execute(); 8 | while ($row = $result->fetchArray(SQLITE3_ASSOC)) { 9 | $currencyId = $row['id']; 10 | $currencies[$currencyId] = $row; 11 | } 12 | 13 | $members = array(); 14 | $query = "SELECT * FROM household WHERE user_id = :userId"; 15 | $stmt = $db->prepare($query); 16 | $stmt->bindValue(':userId', $userId, SQLITE3_INTEGER); 17 | $result = $stmt->execute(); 18 | while ($row = $result->fetchArray(SQLITE3_ASSOC)) { 19 | $memberId = $row['id']; 20 | $members[$memberId] = $row; 21 | $members[$memberId]['count'] = 0; 22 | } 23 | 24 | $payment_methods = array(); 25 | $query = $db->prepare("SELECT * FROM payment_methods WHERE enabled=:enabled AND user_id = :userId ORDER BY `order` ASC"); 26 | $query->bindValue(':enabled', 1, SQLITE3_INTEGER); 27 | $query->bindValue(':userId', $userId, SQLITE3_INTEGER); 28 | $result = $query->execute(); 29 | while ($row = $result->fetchArray(SQLITE3_ASSOC)) { 30 | $payment_methodId = $row['id']; 31 | $payment_methods[$payment_methodId] = $row; 32 | $payment_methods[$payment_methodId]['count'] = 0; 33 | } 34 | 35 | $categories = array(); 36 | $query = "SELECT * FROM categories WHERE user_id = :userId ORDER BY `order` ASC"; 37 | $stmt = $db->prepare($query); 38 | $stmt->bindValue(':userId', $userId, SQLITE3_INTEGER); 39 | $result = $stmt->execute(); 40 | while ($row = $result->fetchArray(SQLITE3_ASSOC)) { 41 | $categoryId = $row['id']; 42 | $categories[$categoryId] = $row; 43 | $categories[$categoryId]['count'] = 0; 44 | } 45 | 46 | $cycles = array(); 47 | $query = "SELECT * FROM cycles"; 48 | $result = $db->query($query); 49 | while ($row = $result->fetchArray(SQLITE3_ASSOC)) { 50 | $cycleId = $row['id']; 51 | $cycles[$cycleId] = $row; 52 | } 53 | 54 | $frequencies = array(); 55 | for ($i = 1; $i <= 366; $i++) { 56 | $frequencies[$i] = array('id' => $i, 'name' => $i); 57 | } 58 | 59 | ?> -------------------------------------------------------------------------------- /includes/i18n/getlang.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /includes/i18n/languages.php: -------------------------------------------------------------------------------- 1 | Language Name 3 | $languages = [ 4 | // English first 5 | "en" => ["name" => "English", "dir" => "ltr"], 6 | // Remaining sorted alphabetically by language code 7 | "cs" => ["name" => "Čeština", "dir" => "ltr"], 8 | "da" => ["name" => "Dansk", "dir" => "ltr"], 9 | "de" => ["name" => "Deutsch", "dir" => "ltr"], 10 | "el" => ["name" => "Ελληνικά", "dir" => "ltr"], 11 | "es" => ["name" => "Español", "dir" => "ltr"], 12 | "fr" => ["name" => "Français", "dir" => "ltr"], 13 | "id" => ["name" => "bahasa indonesia", "dir" => "ltr"], 14 | "it" => ["name" => "Italiano", "dir" => "ltr"], 15 | "jp" => ["name" => "日本語", "dir" => "ltr"], 16 | "ko" => ["name" => "한국어", "dir" => "ltr"], 17 | "nl" => ["name" => "Nederlands", "dir" => "ltr"], 18 | "pl" => ["name" => "Polski", "dir" => "ltr"], 19 | "pt" => ["name" => "Português", "dir" => "ltr"], 20 | "pt_br" => ["name" => "Português Brasileiro", "dir" => "ltr"], 21 | "ru" => ["name" => "Русский", "dir" => "ltr"], 22 | "sl" => ["name" => "Slovenščina", "dir" => "ltr"], 23 | "sr_lat" => ["name" => "Srpski", "dir" => "ltr"], 24 | "sr" => ["name" => "Српски", "dir" => "ltr"], 25 | "tr" => ["name" => "Türkçe", "dir" => "ltr"], 26 | "uk" => ["name" => "Українська", "dir" => "ltr"], 27 | "vi" => ["name" => "Tiếng Việt", "dir" => "ltr"], 28 | "zh_cn" => ["name" => "简体中文", "dir" => "ltr"], 29 | "zh_tw" => ["name" => "繁體中文", "dir" => "ltr"], 30 | 31 | ] 32 | 33 | ?> 34 | -------------------------------------------------------------------------------- /includes/inputvalidation.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /includes/sort_options.php: -------------------------------------------------------------------------------- 1 |
2 | 35 |
-------------------------------------------------------------------------------- /includes/version.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /libs/OTPHP/FactoryInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @author Jim Jagielski (jimjag) 11 | * @author Andy Prevost (codeworxtech) 12 | * @author Brent R. Matzelle (original founder) 13 | * @copyright 2012 - 2020 Marcus Bointon 14 | * @copyright 2010 - 2012 Jim Jagielski 15 | * @copyright 2004 - 2009 Andy Prevost 16 | * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License 17 | * @note This program is distributed in the hope that it will be useful - WITHOUT 18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 | * FITNESS FOR A PARTICULAR PURPOSE. 20 | */ 21 | 22 | namespace PHPMailer\PHPMailer; 23 | 24 | /** 25 | * PHPMailer exception handler. 26 | * 27 | * @author Marcus Bointon 28 | */ 29 | class Exception extends \Exception 30 | { 31 | /** 32 | * Prettify error message output. 33 | * 34 | * @return string 35 | */ 36 | public function errorMessage() 37 | { 38 | return '' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "
\n"; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /libs/Psr/Clock/ClockInterface.php: -------------------------------------------------------------------------------- 1 | prepare($sql); 9 | $stmt->bindParam(':token', $token, SQLITE3_TEXT); 10 | $stmt->bindParam(':userId', $userId, SQLITE3_INTEGER); 11 | $stmt->execute(); 12 | } 13 | $_SESSION = array(); 14 | session_destroy(); 15 | $cookieExpire = time() - 3600; 16 | setcookie('wallos_login', '', $cookieExpire); 17 | $db->close(); 18 | header("Location: ."); 19 | exit(); 20 | ?> -------------------------------------------------------------------------------- /migrations/000001.php: -------------------------------------------------------------------------------- 1 | exec('CREATE TABLE IF NOT EXISTS migrations ( 5 | id INTEGER PRIMARY KEY, 6 | migration TEXT NOT NULL, 7 | migrated_at DATETIME DEFAULT CURRENT_TIMESTAMP 8 | )'); 9 | -------------------------------------------------------------------------------- /migrations/000002.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('payment_methods') where name='enabled'"); 7 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 8 | 9 | if ($columnRequired) { 10 | $db->exec('ALTER TABLE payment_methods ADD COLUMN enabled BOOLEAN DEFAULT 1'); 11 | $db->exec('UPDATE payment_methods SET enabled = 1'); 12 | } 13 | -------------------------------------------------------------------------------- /migrations/000003.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('notifications') where name='from_email'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec('ALTER TABLE notifications ADD COLUMN from_email VARCHAR(255);'); 10 | } 11 | -------------------------------------------------------------------------------- /migrations/000004.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('subscriptions') where name='url'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec('ALTER TABLE subscriptions ADD COLUMN url VARCHAR(255);'); 10 | } 11 | 12 | ?> -------------------------------------------------------------------------------- /migrations/000005.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('user') where name='language'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec('ALTER TABLE user ADD COLUMN language TEXT DEFAULT "en"'); 10 | $db->exec('UPDATE user SET language = "en"'); 11 | } 12 | -------------------------------------------------------------------------------- /migrations/000006.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('fixer') where name='provider'"); 7 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 8 | 9 | if ($columnRequired) { 10 | $db->exec('ALTER TABLE fixer ADD COLUMN provider INT DEFAULT 0'); 11 | $db->exec('UPDATE fixer SET provider = 0'); 12 | } -------------------------------------------------------------------------------- /migrations/000007.php: -------------------------------------------------------------------------------- 1 | exec('CREATE TABLE IF NOT EXISTS settings ( 7 | dark_theme BOOLEAN DEFAULT 0, 8 | monthly_price BOOLEAN DEFAULT 0, 9 | convert_currency BOOLEAN DEFAULT 0, 10 | remove_background BOOLEAN DEFAULT 0 11 | )'); 12 | 13 | 14 | $db->exec('INSERT INTO settings (dark_theme, monthly_price, convert_currency, remove_background) VALUES (0, 0, 0, 0)'); 15 | 16 | -------------------------------------------------------------------------------- /migrations/000008.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('subscriptions') WHERE name='inactive'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec('ALTER TABLE subscriptions ADD COLUMN inactive BOOLEAN DEFAULT false'); 10 | $db->exec('UPDATE subscriptions SET inactive = false'); 11 | } 12 | -------------------------------------------------------------------------------- /migrations/000009.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('household') where name='email'"); 7 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 8 | 9 | if ($columnRequired) { 10 | $db->exec('ALTER TABLE household ADD COLUMN email TEXT DEFAULT ""'); 11 | } -------------------------------------------------------------------------------- /migrations/000010.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('categories') WHERE name='order'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec('ALTER TABLE categories ADD COLUMN `order` INTEGER DEFAULT 0'); 10 | $db->exec('UPDATE categories SET `order` = id'); 11 | } 12 | 13 | 14 | ?> -------------------------------------------------------------------------------- /migrations/000011.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('payment_methods') WHERE name='order'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec('ALTER TABLE payment_methods ADD COLUMN `order` INTEGER DEFAULT 0'); 10 | $db->exec('UPDATE payment_methods SET `order` = id'); 11 | } 12 | 13 | 14 | ?> -------------------------------------------------------------------------------- /migrations/000012.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('notifications') WHERE name='encryption'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec('ALTER TABLE notifications ADD COLUMN `encryption` TEXT DEFAULT "tls"'); 10 | $db->exec('UPDATE notifications SET `encryption` = "tls"'); 11 | } 12 | ?> -------------------------------------------------------------------------------- /migrations/000013.php: -------------------------------------------------------------------------------- 1 | prepare($sql); 10 | $result = $stmt->execute(); 11 | $row = $result->fetchArray(SQLITE3_ASSOC); 12 | 13 | if ($row) { 14 | $avatar = $row['avatar']; 15 | 16 | if (strlen($avatar) < 2) { 17 | $avatarFullPath = "images/avatars/" . $avatar . ".svg"; 18 | $sql = "UPDATE user SET avatar = :avatarFullPath"; 19 | $stmt = $db->prepare($sql); 20 | $stmt->bindValue(':avatarFullPath', $avatarFullPath, SQLITE3_TEXT); 21 | $stmt->execute(); 22 | } 23 | } 24 | 25 | ?> -------------------------------------------------------------------------------- /migrations/000014.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('settings') where name='color_theme'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec("ALTER TABLE settings ADD COLUMN color_theme TEXT DEFAULT 'blue'"); 10 | $db->exec('UPDATE settings SET `color_theme` = "blue"'); 11 | } 12 | 13 | // This migrations adds custom_colors table to the database, so the user can set custom accent colors to the application 14 | 15 | $customColorsTableQuery = $db->query("SELECT * FROM sqlite_master WHERE type='table' AND name='custom_colors'"); 16 | $customColorsTableRequired = $customColorsTableQuery->fetchArray(SQLITE3_ASSOC) === false; 17 | 18 | if ($customColorsTableRequired) { 19 | $db->exec("CREATE TABLE custom_colors ( 20 | main_color TEXT NOT NULL, 21 | accent_color TEXT NOT NULL, 22 | hover_color TEXT NOT NULL 23 | )"); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /migrations/000015.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('settings') where name='hide_disabled'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec("ALTER TABLE settings ADD COLUMN hide_disabled BOOLEAN DEFAULT 0"); 10 | $db->exec('UPDATE settings SET `hide_disabled` = 0'); 11 | } -------------------------------------------------------------------------------- /migrations/000017.php: -------------------------------------------------------------------------------- 1 | exec('CREATE TABLE IF NOT EXISTS pushover_notifications ( 9 | enabled BOOLEAN DEFAULT 0, 10 | user_key TEXT DEFAULT "", 11 | token TEXT DEFAULT "" 12 | )'); 13 | 14 | $db->exec('CREATE TABLE IF NOT EXISTS discord_notifications ( 15 | enabled BOOLEAN DEFAULT 0, 16 | webhook_url TEXT DEFAULT "", 17 | bot_username TEXT DEFAULT "", 18 | bot_avatar_url TEXT DEFAULT "" 19 | )'); -------------------------------------------------------------------------------- /migrations/000018.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('users') where name='budget'"); 9 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 10 | 11 | if ($columnRequired) { 12 | $db->exec('ALTER TABLE user ADD COLUMN budget INTEGER DEFAULT 0'); 13 | } 14 | 15 | ?> -------------------------------------------------------------------------------- /migrations/000019.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('subscriptions') where name='notify_days_before'"); 9 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 10 | 11 | if ($columnRequired) { 12 | $db->exec('ALTER TABLE subscriptions ADD COLUMN notify_days_before INTEGER DEFAULT 0'); 13 | } 14 | 15 | ?> -------------------------------------------------------------------------------- /migrations/000021.php: -------------------------------------------------------------------------------- 1 | exec('CREATE TABLE IF NOT EXISTS ntfy_notifications ( 9 | enabled BOOLEAN DEFAULT 0, 10 | host TEXT DEFAULT "", 11 | topic TEXT DEFAULT "", 12 | headers TEXT DEFAULT "", 13 | user_id INTEGER, 14 | FOREIGN KEY (user_id) REFERENCES user(id) 15 | )'); -------------------------------------------------------------------------------- /migrations/000022.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('admin') where name='login_disabled'"); 9 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 10 | 11 | if ($columnRequired) { 12 | $db->exec('ALTER TABLE admin ADD COLUMN login_disabled BOOLEAN DEFAULT 0'); 13 | } 14 | 15 | ?> -------------------------------------------------------------------------------- /migrations/000023.php: -------------------------------------------------------------------------------- 1 | exec('CREATE TABLE IF NOT EXISTS custom_css_style ( 9 | css TEXT DEFAULT "", 10 | user_id INTEGER, 11 | FOREIGN KEY (user_id) REFERENCES user(id) 12 | )'); -------------------------------------------------------------------------------- /migrations/000024.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('subscriptions') where name='cancellation_date'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec('ALTER TABLE subscriptions ADD COLUMN cancellation_date DATE;'); 10 | } -------------------------------------------------------------------------------- /migrations/000025.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('settings') where name='disabled_to_bottom'"); 7 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 8 | 9 | if ($columnRequired) { 10 | $db->exec('ALTER TABLE settings ADD COLUMN disabled_to_bottom BOOLEAN DEFAULT 0'); 11 | } 12 | 13 | $columnQuery = $db->query("SELECT * FROM pragma_table_info('admin') where name='latest_version'"); 14 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 15 | 16 | if ($columnRequired) { 17 | $db->exec("ALTER TABLE admin ADD COLUMN latest_version TEXT DEFAULT 'v2.21.1'"); 18 | } 19 | 20 | $columnQuery = $db->query("SELECT * FROM pragma_table_info('admin') where name='update_notification'"); 21 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 22 | 23 | if ($columnRequired) { 24 | $db->exec('ALTER TABLE admin ADD COLUMN update_notification BOOLEAN DEFAULT 0'); 25 | } -------------------------------------------------------------------------------- /migrations/000026.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('email_notifications') where name='other_emails'"); 7 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 8 | 9 | if ($columnRequired) { 10 | $db->exec('ALTER TABLE email_notifications ADD COLUMN other_emails TEXT DEFAULT "";'); 11 | } 12 | 13 | $columnQuery = $db->query("SELECT * FROM pragma_table_info('settings') where name='show_original_price'"); 14 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 15 | 16 | if ($columnRequired) { 17 | $db->exec('ALTER TABLE settings ADD COLUMN show_original_price BOOLEAN DEFAULT 0'); 18 | } -------------------------------------------------------------------------------- /migrations/000027.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('user') where name='totp_enabled'"); 8 | 9 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 10 | 11 | if ($columnRequired) { 12 | $db->exec('ALTER TABLE user ADD COLUMN totp_enabled BOOLEAN DEFAULT 0'); 13 | } 14 | 15 | $db->exec('CREATE TABLE IF NOT EXISTS totp ( 16 | user_id INTEGER NOT NULL, 17 | totp_secret TEXT NOT NULL, 18 | backup_codes TEXT NOT NULL, 19 | last_totp_used INTEGER DEFAULT 0, 20 | FOREIGN KEY(user_id) REFERENCES user(id) 21 | )'); -------------------------------------------------------------------------------- /migrations/000028.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('settings') where name='mobile_nav'"); 7 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 8 | 9 | if ($columnRequired) { 10 | $db->exec('ALTER TABLE settings ADD COLUMN mobile_nav BOOLEAN DEFAULT 0'); 11 | } -------------------------------------------------------------------------------- /migrations/000029.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('user') where name='api_key'"); 8 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 9 | 10 | if ($columnRequired) { 11 | $db->exec('ALTER TABLE user ADD COLUMN api_key TEXT'); 12 | } 13 | 14 | /** @noinspection PhpUndefinedVariableInspection */ 15 | $users = $db->query('SELECT * FROM user'); 16 | while ($user = $users->fetchArray(SQLITE3_ASSOC)) { 17 | if (empty($user['api_key'])) { 18 | $apiKey = bin2hex(random_bytes(32)); 19 | $db->exec('UPDATE user SET api_key = "' . $apiKey . '" WHERE id = ' . $user['id']); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /migrations/000030.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('webhook_notifications') where name='ignore_ssl'"); 10 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 11 | 12 | if ($columnRequired) { 13 | $db->exec('ALTER TABLE webhook_notifications ADD COLUMN ignore_ssl INTEGER DEFAULT 0'); 14 | } 15 | 16 | // Add the ignore_ssl column to the ntfy_notifications table 17 | 18 | /** @noinspection PhpUndefinedVariableInspection */ 19 | $columnQuery = $db->query("SELECT * FROM pragma_table_info('ntfy_notifications') where name='ignore_ssl'"); 20 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 21 | 22 | if ($columnRequired) { 23 | $db->exec('ALTER TABLE ntfy_notifications ADD COLUMN ignore_ssl INTEGER DEFAULT 0'); 24 | } 25 | 26 | // Add the ignore_ssl column to the gotify_notifications table 27 | 28 | /** @noinspection PhpUndefinedVariableInspection */ 29 | $columnQuery = $db->query("SELECT * FROM pragma_table_info('gotify_notifications') where name='ignore_ssl'"); 30 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 31 | 32 | if ($columnRequired) { 33 | $db->exec('ALTER TABLE gotify_notifications ADD COLUMN ignore_ssl INTEGER DEFAULT 0'); 34 | } 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /migrations/000031.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('subscriptions') where name='replacement_subscription_id'"); 7 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 8 | 9 | if ($columnRequired) { 10 | $db->exec('ALTER TABLE subscriptions ADD COLUMN replacement_subscription_id INTEGER DEFAULT NULL'); 11 | } 12 | 13 | 14 | ?> -------------------------------------------------------------------------------- /migrations/000032.php: -------------------------------------------------------------------------------- 1 | query("SELECT name FROM sqlite_master WHERE type='table' AND name='total_yearly_cost'"); 8 | $tableRequired = $tableQuery->fetchArray(SQLITE3_ASSOC) === false; 9 | 10 | if ($tableRequired) { 11 | $db->exec('CREATE TABLE total_yearly_cost ( 12 | id INTEGER PRIMARY KEY AUTOINCREMENT, 13 | user_id INTEGER NOT NULL, 14 | date INTEGER NOT NULL, 15 | cost REAL NOT NULL, 16 | currency TEXT NOT NULL 17 | )'); 18 | } 19 | 20 | /** @noinspection PhpUndefinedVariableInspection */ 21 | $columnQuery = $db->query("PRAGMA table_info(subscriptions)"); 22 | $columns = []; 23 | while ($column = $columnQuery->fetchArray(SQLITE3_ASSOC)) { 24 | $columns[] = $column['name']; 25 | } 26 | 27 | if (!in_array('start_date', $columns)) { 28 | $db->exec('ALTER TABLE subscriptions ADD COLUMN start_date INTEGER DEFAULT NULL'); 29 | } 30 | 31 | if (!in_array('auto_renew', $columns)) { 32 | $db->exec('ALTER TABLE subscriptions ADD COLUMN auto_renew INTEGER DEFAULT 1'); 33 | } 34 | 35 | ?> -------------------------------------------------------------------------------- /migrations/000033.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('settings') where name='show_subscription_progress'"); 6 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 7 | 8 | if ($columnRequired) { 9 | $db->exec("ALTER TABLE settings ADD COLUMN show_subscription_progress BOOLEAN DEFAULT 0"); 10 | $db->exec('UPDATE settings SET `show_subscription_progress` = 0'); 11 | } -------------------------------------------------------------------------------- /migrations/000034.php: -------------------------------------------------------------------------------- 1 | exec('UPDATE subscriptions SET `notify_days_before` = -1 WHERE `notify_days_before` = 0'); -------------------------------------------------------------------------------- /migrations/000035.php: -------------------------------------------------------------------------------- 1 | exec('DELETE FROM total_yearly_cost'); 5 | -------------------------------------------------------------------------------- /migrations/000036.php: -------------------------------------------------------------------------------- 1 | query("SELECT * FROM pragma_table_info('webhook_notifications') where name='cancelation_payload'"); 9 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false; 10 | 11 | if ($columnRequired) { 12 | $db->exec("ALTER TABLE webhook_notifications ADD COLUMN cancelation_payload TEXT DEFAULT ''"); 13 | } 14 | 15 | $columnQuery = $db->query("SELECT * FROM pragma_table_info('webhook_notifications') where name='iterator'"); 16 | $columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) !== false; 17 | if ($columnRequired) { 18 | $db->exec("ALTER TABLE webhook_notifications DROP COLUMN iterator"); 19 | } 20 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes 1; 3 | 4 | error_log /var/log/nginx/error.log warn; 5 | pid /var/run/nginx.pid; 6 | 7 | events { 8 | worker_connections 1024; 9 | } 10 | 11 | http { 12 | include /etc/nginx/mime.types; 13 | default_type application/octet-stream; 14 | 15 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 16 | '$status $body_bytes_sent "$http_referer" ' 17 | '"$http_user_agent" "$http_x_forwarded_for"'; 18 | 19 | access_log /var/log/nginx/access.log main; 20 | 21 | sendfile on; 22 | keepalive_timeout 65; 23 | 24 | server { 25 | listen 80; 26 | server_name localhost; 27 | 28 | location / { 29 | root /var/www/html; 30 | index index.php; 31 | } 32 | 33 | location ~ \.php$ { 34 | root /var/www/html; 35 | fastcgi_pass 127.0.0.1:9000; 36 | fastcgi_index index.php; 37 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 38 | include fastcgi_params; 39 | } 40 | 41 | location ~ \.db$ { 42 | deny all; 43 | return 403; 44 | } 45 | 46 | location ~* images/uploads/logos/.*\.php$ { 47 | deny all; 48 | return 403; 49 | } 50 | 51 | location ~* \.tmp/.*\.php$ { 52 | deny all; 53 | return 403; 54 | } 55 | } 56 | 57 | include /etc/nginx/conf.d/*.conf; 58 | } -------------------------------------------------------------------------------- /nginx.default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name your_domain_or_ip; # Change to your domain or IP 4 | 5 | root /var/www/html; # Change to your web root directory 6 | 7 | location / { 8 | try_files $uri $uri/ /index.php?$args; 9 | } 10 | 11 | location ~ \.php$ { 12 | include fastcgi_params; 13 | fastcgi_pass unix:/var/run/php-fpm.sock; # Adjust the path if necessary 14 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 15 | } 16 | 17 | # Additional configuration if needed 18 | } -------------------------------------------------------------------------------- /screenshots/wallos-calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/screenshots/wallos-calendar.png -------------------------------------------------------------------------------- /screenshots/wallos-dashboard-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/screenshots/wallos-dashboard-dark.png -------------------------------------------------------------------------------- /screenshots/wallos-dashboard-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/screenshots/wallos-dashboard-light.png -------------------------------------------------------------------------------- /screenshots/wallos-dashboard-mobile-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/screenshots/wallos-dashboard-mobile-dark.png -------------------------------------------------------------------------------- /screenshots/wallos-dashboard-mobile-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/screenshots/wallos-dashboard-mobile-light.png -------------------------------------------------------------------------------- /screenshots/wallos-form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/screenshots/wallos-form.png -------------------------------------------------------------------------------- /screenshots/wallos-stats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/screenshots/wallos-stats.png -------------------------------------------------------------------------------- /scripts/all.js: -------------------------------------------------------------------------------- 1 | if ('serviceWorker' in navigator) { 2 | window.addEventListener('load', function() { 3 | navigator.serviceWorker.register('service-worker.js').then(function(registration) { 4 | //console.log('ServiceWorker registration successful with scope: ', registration.scope); 5 | }, function(err) { 6 | console.log('ServiceWorker registration failed: ', err); 7 | }); 8 | }); 9 | } -------------------------------------------------------------------------------- /scripts/i18n/cs.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Chyba při načítání předplatného:", 4 | error_fetching_image_results: "Chyba při načítání výsledků obrázků:", 5 | subscription_deleted: "Předplatné odstraněno", 6 | error_deleting_subscription: "Chyba při odstraňování předplatného", 7 | failed_to_load_subscription: "Nepodařilo se načíst předplatné", 8 | edit_subscription: "Upravit předplatné", 9 | add_subscription: "Přidat předplatné", 10 | confirm_delete_subscription: "Opravdu chcete odstranit toto předplatné?", 11 | // Settings 12 | network_response_error: "Odezva sítě nebyla v pořádku", 13 | failed_add_member: "Nepodařilo se přidat člena", 14 | member: "Člen", 15 | email: "E-mail", 16 | save_member: "Uložit člena", 17 | delete_member: "Odstranit člena", 18 | failed_remove_member: "Nepodařilo se odebrat člena", 19 | failed_save_member: "Nepodařilo se uložit člena", 20 | failed_add_category: "Nepodařilo se přidat kategorii", 21 | category: "Kategorie", 22 | save_category: "Uložit kategorii", 23 | delete_category: "Odstranit kategorii", 24 | failed_remove_category: "Nepodařilo se odebrat kategorii", 25 | currency: "Měna", 26 | currency_code: "Kód měny", 27 | save_currency: "Uložit měnu", 28 | delete_currency: "Odstranit měnu", 29 | failed_remove_currency: "Nepodařilo se odebrat měnu", 30 | failed_save_currency: "Nepodařilo se uložit měnu", 31 | cant_disable_payment_in_use: "Nelze zakázat používanou platbu", 32 | failed_save_payment_method: "Nepodařilo se uložit platební metodu", 33 | unknown_error: "Neznámá chyba, zkuste to prosím znovu.", 34 | error_saving_notification_data: "Chyba při ukládání dat oznámení", 35 | error_sending_notification: "Chyba při odesílání oznámení", 36 | delete_account_confirmation: "Opravdu chcete odstranit svůj účet?", 37 | this_will_delete_all_data: "Tím se odstraní všechna vaše data a nelze to vrátit zpět. Pokračovat?", 38 | success: "Úspěch", 39 | copied_to_clipboard: "Zkopírováno do schránky", 40 | // Calendar 41 | price: "Cena", 42 | category: "Kategorie", 43 | paid_by: "Platí", 44 | payment_method: "Platební metoda", 45 | notes: "Poznámky", 46 | export: "Exportovat", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/da.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Fejl ved genindlæsning af abonnement:", 4 | error_fetching_image_results: "Fejl ved hentning af billedresultater:", 5 | subscription_deleted: "Abonnement slettet", 6 | error_deleting_subscription: "Fejl ved sletning af abonnement", 7 | failed_to_load_subscription: "Kunne ikke indlæse abonnement", 8 | edit_subscription: "Redigér abonnement", 9 | add_subscription: "Tilføj abonnement", 10 | confirm_delete_subscription: "Er du sikker på, at du vil slette dette abonnement?", 11 | // Settings 12 | network_response_error: "Netværkssvaret var ikke i orden", 13 | failed_add_member: "Kunne ikke tilføje medlem", 14 | member: "Medlem", 15 | email: "E-mail", 16 | save_member: "Gem medlem", 17 | delete_member: "Slet medlem", 18 | failed_remove_member: "Kunne ikke fjerne medlem", 19 | failed_save_member: "Kunne ikke gemme medlem", 20 | failed_add_category: "Kunne ikke tilføje kategori", 21 | category: "Kategori", 22 | save_category: "Gem kategori", 23 | delete_category: "Slet kategori", 24 | failed_remove_category: "Kunne ikke fjerne kategori", 25 | currency: "Valuta", 26 | currency_code: "Valutakode", 27 | save_currency: "Gem valuta", 28 | delete_currency: "Slet valuta", 29 | failed_remove_currency: "Kunne ikke fjerne valuta", 30 | failed_save_currency: "Kunne ikke gemme valuta", 31 | cant_disable_payment_in_use: "Kan ikke deaktivere betalingsmetode i brug", 32 | failed_save_payment_method: "Kunne ikke gemme betalingsmetode", 33 | unknown_error: "Ukendt fejl, prøv venligst igen.", 34 | error_saving_notification_data: "Fejl ved lagring af notifikationsdata", 35 | error_sending_notification: "Fejl ved afsendelse af notifikation", 36 | delete_account_confirmation: "Er du sikker på, at du vil slette din konto?", 37 | this_will_delete_all_data: "Dette vil slette alle dine data og kan ikke fortrydes. Fortsæt?", 38 | success: "Succes", 39 | copied_to_clipboard: "Kopieret til udklipsholder", 40 | // Calendar 41 | price: "Pris", 42 | category: "Kategori", 43 | paid_by: "Betalt af", 44 | payment_method: "Betalingsmetode", 45 | notes: "Noter", 46 | export: "Eksportér", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/en.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Error reloading subscription:", 4 | error_fetching_image_results: "Error fetching image results:", 5 | subscription_deleted: "Subscription deleted", 6 | error_deleting_subscription: "Error deleting subscription", 7 | failed_to_load_subscription: "Failed to load subscription", 8 | edit_subscription: "Edit subscription", 9 | add_subscription: "Add subscription", 10 | confirm_delete_subscription: "Are you sure you want to delete this subscription?", 11 | // Settings 12 | network_response_error: "Network response was not ok", 13 | failed_add_member: "Failed to add member", 14 | member: "Member", 15 | email: "Email", 16 | save_member: "Save member", 17 | delete_member: "Delete member", 18 | failed_remove_member: "Failed to remove member", 19 | failed_save_member: "Failed to save member", 20 | failed_add_category: "Failed to add category", 21 | category: "Category", 22 | save_category: "Save category", 23 | delete_category: "Delete category", 24 | failed_remove_category: "Failed to remove category", 25 | currency: "Currency", 26 | currency_code: "Currency code", 27 | save_currency: "Save currency", 28 | delete_currency: "Delete currency", 29 | failed_remove_currency: "Failed to remove currency", 30 | failed_save_currency: "Failed to save currency", 31 | cant_disable_payment_in_use: "Can't disable payment in use", 32 | failed_save_payment_method: "Failed to save payment method", 33 | unknown_error: "Unknown error, please try again.", 34 | error_saving_notification_data: "Error saving notification data", 35 | error_sending_notification: "Error sending notification", 36 | delete_account_confirmation: "Are you sure you want to delete your account?", 37 | this_will_delete_all_data: "This will delete all your data and can't be undone. Continue?", 38 | success: "Success", 39 | copied_to_clipboard: "Copied to clipboard", 40 | // Calendar 41 | price: "Price", 42 | category: "Category", 43 | paid_by: "Paid by", 44 | payment_method: "Payment method", 45 | notes: "Notes", 46 | export: "Export", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/es.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Error al recargar la suscripción:", 4 | error_fetching_image_results: "Error al obtener resultados de imágenes:", 5 | subscription_deleted: "Suscripción eliminada", 6 | error_deleting_subscription: "Error al eliminar la suscripción", 7 | failed_to_load_subscription: "Error al cargar la suscripción", 8 | edit_subscription: "Editar suscripción", 9 | add_subscription: "Añadir suscripción", 10 | confirm_delete_subscription: "¿Estás seguro de que quieres eliminar esta suscripción?", 11 | // Settings 12 | network_response_error: "Error en la respuesta de la red", 13 | failed_add_member: "Error al añadir miembro", 14 | member: "Miembro", 15 | email: "Correo electrónico", 16 | save_member: "Guardar miembro", 17 | delete_member: "Eliminar miembro", 18 | failed_remove_member: "Error al eliminar miembro", 19 | failed_save_member: "Error al guardar miembro", 20 | failed_add_category: "Error al añadir categoría", 21 | category: "Categoría", 22 | save_category: "Guardar categoría", 23 | delete_category: "Eliminar categoría", 24 | failed_remove_category: "Error al eliminar categoría", 25 | currency: "Moneda", 26 | currency_code: "Código de moneda", 27 | save_currency: "Guardar moneda", 28 | delete_currency: "Eliminar moneda", 29 | failed_remove_currency: "Error al eliminar moneda", 30 | failed_save_currency: "Error al guardar moneda", 31 | cant_disable_payment_in_use: "No se puede desactivar el método de pago en uso", 32 | failed_save_payment_method: "Error al guardar el método de pago", 33 | unknown_error: "Error desconocido, por favor inténtalo de nuevo.", 34 | error_saving_notification_data: "Error al guardar los datos de notificación", 35 | error_sending_notification: "Error al enviar la notificación", 36 | delete_account_confirmation: "¿Estás seguro de que quieres eliminar tu cuenta?", 37 | this_will_delete_all_data: "Esto eliminará todos tus datos y no se podrán recuperar. ¿Continuar?", 38 | success: "Éxito", 39 | copied_to_clipboard: "Copiado al portapapeles", 40 | // Calendar 41 | price: "Precio", 42 | category: "Categoría", 43 | paid_by: "Pagado por", 44 | payment_method: "Método de pago", 45 | notes: "Notas", 46 | export: "Exportar", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/getlang.js: -------------------------------------------------------------------------------- 1 | function translate(key) { 2 | if (i18n[key]) { 3 | return i18n[key]; 4 | } else { 5 | return "[Translation Missing]"; 6 | } 7 | } -------------------------------------------------------------------------------- /scripts/i18n/jp.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "定期購入の再読み込みエラー:", 4 | error_fetching_image_results: "画像取得結果エラー:", 5 | subscription_deleted: "定期購入の削除", 6 | error_deleting_subscription: "定期購入の削除エラー", 7 | failed_to_load_subscription: "定期購入の読み込みに失敗しました", 8 | edit_subscription: "定期購入の編集", 9 | add_subscription: "定期購入の追加", 10 | confirm_delete_subscription: "この定期購入を削除してもよろしいですか?", 11 | // Settings 12 | network_response_error: "ネットワークの応答異常", 13 | failed_add_member: "世帯員の追加に失敗", 14 | member: "世帯員", 15 | email: "メール", 16 | save_member: "世帯員の保存", 17 | delete_member: "世帯員の削除", 18 | failed_remove_member: "世帯員の削除に失敗", 19 | failed_save_member: "世帯員の削除に失敗", 20 | failed_add_category: "カテゴリの追加に失敗", 21 | category: "カテゴリ", 22 | save_category: "カテゴリの保存", 23 | delete_category: "カテゴリの削除", 24 | failed_remove_category: "カテゴリの削除に失敗", 25 | currency: "通貨", 26 | currency_code: "通貨コード", 27 | save_currency: "通貨の保存", 28 | delete_currency: "通貨の削除", 29 | failed_remove_currency: "通貨の削除に失敗", 30 | failed_save_currency: "通貨の保存に失敗", 31 | cant_disable_payment_in_use: "使用中の支払いは無効にできません", 32 | failed_save_payment_method: "支払い方法の保存に失敗", 33 | unknown_error: "不明なエラー。もう一度試してください。", 34 | error_saving_notification_data: "通知データの保存エラー", 35 | error_sending_notification: "通知の送信エラー", 36 | delete_account_confirmation: "アカウントを削除してもよろしいですか?", 37 | this_will_delete_all_data: "これによりすべてのデータが削除され、元に戻すことはできません。続行しますか?", 38 | success: "成功", 39 | copied_to_clipboard: "クリップボードにコピーされました", 40 | // Calendar 41 | price: "価格", 42 | category: "カテゴリ", 43 | paid_by: "支払い者", 44 | payment_method: "支払い方法", 45 | notes: "メモ", 46 | export: "エクスポート", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/ko.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "고독 새로고침 중 에러가 발생했습니다:", 4 | error_fetching_image_results: "이미지 가져오기에 실패했습니다:", 5 | subscription_deleted: "구독이 삭제되었습니다", 6 | error_deleting_subscription: "구독 삭제중 에러가 발생했습니다", 7 | failed_to_load_subscription: "구독 불러오기에 실패했습니다", 8 | edit_subscription: "구독 수정", 9 | add_subscription: "구독 추가", 10 | confirm_delete_subscription: "이 구독을 정말 삭제하시겠습니까?", 11 | // Settings 12 | network_response_error: "네트워크 응답 오류가 발생했습니다", 13 | failed_add_member: "구성원 추가에 실패했습니다", 14 | member: "구성원", 15 | email: "이메일", 16 | save_member: "구성원 저장", 17 | delete_member: "구성원 삭제", 18 | failed_remove_member: "구성원 삭제에 실패했습니다", 19 | failed_save_member: "구성원 저장에 실패했습니다", 20 | failed_add_category: "카테고리 추가에 실패했습니다", 21 | category: "카테고리", 22 | save_category: "카테고리 저장", 23 | delete_category: "카테고리 삭제", 24 | failed_remove_category: "카테고리 삭제에 실패했습니다", 25 | currency: "통화", 26 | currency_code: "통화 코드", 27 | save_currency: "통화 저장", 28 | delete_currency: "통화 삭제", 29 | failed_remove_currency: "통화 삭제에 실패했습니다", 30 | failed_save_currency: "통화 저장에 실패했습니다", 31 | cant_disable_payment_in_use: "사용 중인 결제 수단을 비활성화 할 수 없습니다", 32 | failed_save_payment_method: "결제 수단 저장에 실패했습니다", 33 | unknown_error: "알 수 없는 에러입니다. 다시 시도해 주세요.", 34 | error_saving_notification_data: "알림 데이터 저장 에러", 35 | error_sending_notification: "알림 전송 에러", 36 | delete_account_confirmation: "정말 계정을 삭제하시겠습니까?", 37 | this_will_delete_all_data: "이로 인해 모든 데이터가 삭제되며 복구할 수 없습니다. 계속하시겠습니까?", 38 | success: "성공", 39 | copied_to_clipboard: "클립보드에 복사되었습니다", 40 | // Calendar 41 | price: "가격", 42 | category: "카테고리", 43 | paid_by: "지불자", 44 | payment_method: "결제 수단", 45 | notes: "메모", 46 | export: "내보내기", 47 | }; 48 | -------------------------------------------------------------------------------- /scripts/i18n/nl.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Fout bij het herladen van abonnement:", 4 | error_fetching_image_results: "Fout bij het ophalen van afbeeldingsresultaten:", 5 | subscription_deleted: "Abonnement verwijderd", 6 | error_deleting_subscription: "Fout bij het verwijderen van abonnement", 7 | failed_to_load_subscription: "Laden van abonnement mislukt", 8 | edit_subscription: "Abonnement bewerken", 9 | add_subscription: "Abonnement toevoegen", 10 | confirm_delete_subscription: "Weet u zeker dat u dit abonnement wilt verwijderen?", 11 | // Settings 12 | network_response_error: "Netwerkreactie was niet in orde", 13 | failed_add_member: "Lid toevoegen mislukt", 14 | member: "Lid", 15 | email: "E-mail", 16 | save_member: "Lid opslaan", 17 | delete_member: "Lid verwijderen", 18 | failed_remove_member: "Lid verwijderen mislukt", 19 | failed_save_member: "Lid opslaan mislukt", 20 | failed_add_category: "Categorie toevoegen mislukt", 21 | category: "Categorie", 22 | save_category: "Categorie opslaan", 23 | delete_category: "Categorie verwijderen", 24 | failed_remove_category: "Categorie verwijderen mislukt", 25 | currency: "Valuta", 26 | currency_code: "Valutacode", 27 | save_currency: "Valuta opslaan", 28 | delete_currency: "Valuta verwijderen", 29 | failed_remove_currency: "Valuta verwijderen mislukt", 30 | failed_save_currency: "Valuta opslaan mislukt", 31 | cant_disable_payment_in_use: "Kan in gebruik zijnde betaalmethode niet uitschakelen", 32 | failed_save_payment_method: "Betaalmethode opslaan mislukt", 33 | unknown_error: "Onbekende fout, probeer het opnieuw.", 34 | error_saving_notification_data: "Fout bij opslaan van notificatiegegevens", 35 | error_sending_notification: "Fout bij versturen van notificatie", 36 | delete_account_confirmation: "Weet je zeker dat je je account wilt verwijderen?", 37 | this_will_delete_all_data: "Dit zal al je gegevens verwijderen en kan niet ongedaan worden gemaakt. Doorgaan?", 38 | success: "Succes", 39 | copied_to_clipboard: "Gekopieerd naar klembord", 40 | // Calendar 41 | price: "Prijs", 42 | category: "Categorie", 43 | paid_by: "Betaald door", 44 | payment_method: "Betaalmethode", 45 | notes: "Notities", 46 | export: "Exporteren" 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/pl.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Błąd przeładowania subskrypcji:", 4 | error_fetching_image_results: "Błąd pobierania wyników obrazu:", 5 | subscription_deleted: "Subskrypcja usunięta", 6 | error_deleting_subscription: "Błąd usunięcia subskrypcji", 7 | failed_to_load_subscription: "Nie udało się załadować subskrypcji", 8 | edit_subscription: "Edytuj subskrypcję", 9 | add_subscription: "Dodaj subskrypcję", 10 | confirm_delete_subscription: "Czy na pewno chcesz usunąć tę subskrypcję?", 11 | // Settings 12 | network_response_error: "Odpowiedź sieciowa nie była prawidłowa", 13 | failed_add_member: "Nie udało się dodać użytkownika", 14 | member: "Użytkownik", 15 | email: "E-mail", 16 | save_member: "Zapisz użytkownika", 17 | delete_member: "Usuń użytkownika", 18 | failed_remove_member: "Nie udało się usunąć użytkownika", 19 | failed_save_member: "Nie udało się zapisać użytkownika", 20 | failed_add_category: "Nie udało się dodać kategorii", 21 | category: "Kategoria", 22 | save_category: "Zapisz kategorię", 23 | delete_category: "Usuń kategorię", 24 | failed_remove_category: "Nie udało się usunąć kategorii", 25 | currency: "Waluta", 26 | currency_code: "Kod waluty", 27 | save_currency: "Zapisz walutę", 28 | delete_currency: "Usuń walutę", 29 | failed_remove_currency: "Nie udało się usunąć waluty", 30 | failed_save_currency: "Nie udało się zapisać waluty", 31 | cant_disable_payment_in_use: "Nie można wyłączyć płatności w użyciu", 32 | failed_save_payment_method: "Nie udało się zapisać metody płatności", 33 | unknown_error: "Nieznany błąd, spróbuj ponownie.", 34 | error_saving_notification_data: "Błąd zapisywania danych powiadomienia", 35 | error_sending_notification: "Błąd wysyłania powiadomienia", 36 | delete_account_confirmation: "Czy na pewno chcesz usunąć swoje konto?", 37 | this_will_delete_all_data: "Spowoduje to usunięcie wszystkich danych i nie będzie można tego cofnąć. Kontynuować?", 38 | success: "Sukces", 39 | copied_to_clipboard: "Skopiowano do schowka", 40 | // Calendar 41 | price: "Cena", 42 | category: "Kategoria", 43 | paid_by: "Zapłacone przez", 44 | payment_method: "Metoda płatności", 45 | notes: "Notatki", 46 | export: "Eksport", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/pt_br.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Erro ao recarregar assinaturas:", 4 | error_fetching_image_results: "Erro ao carregar resultados de imagens:", 5 | subscription_deleted: "Assinatura excluída", 6 | error_deleting_subscription: "Erro ao excluir assinatura", 7 | failed_to_load_subscription: "Erro ao carregar assinaturas", 8 | edit_subscription: "Editar assinatura", 9 | add_subscription: "Adicionar assinatura", 10 | confirm_delete_subscription: "Você tem certeza que deseja excluir essa assinatura?", 11 | // Settings 12 | network_response_error: "Resposta da rede não foi OK", 13 | failed_add_member: "Erro ao adicionar membro", 14 | member: "Membro", 15 | email: "Email", 16 | save_member: "Salvar membro", 17 | delete_member: "Excluir membro", 18 | failed_remove_member: "Erro ao excluir membro", 19 | failed_save_member: "Erro ao salvar membro", 20 | failed_add_category: "Erro ao adicionar categoria", 21 | category: "Categoria", 22 | save_category: "Salvar categoria", 23 | delete_category: "Excluir categoria", 24 | failed_remove_category: "Erro ao excluir categoria", 25 | currency: "Moeda", 26 | currency_code: "Código da moeda", 27 | save_currency: "Salvar moeda", 28 | delete_currency: "Excluir moeda", 29 | failed_remove_currency: "Erro ao excluir moeda", 30 | failed_save_currency: "Error ao salvar moeda", 31 | cant_disable_payment_in_use: "Não é possível desativar uma moeda em uso", 32 | failed_save_payment_method: "Erro ao salvar o método de pagamento", 33 | unknown_error: "Erro desconhecido. Por favor, tente novamente", 34 | error_saving_notification_data: "Erro ao salvar dados da notificação", 35 | error_sending_notification: "Erro ao enviar notificação", 36 | delete_account_confirmation: "Você tem certeza que deseja excluir sua conta?", 37 | this_will_delete_all_data: "Isso excluirá todos os seus dados e não poderão ser recuperados. Continuar?", 38 | success: "Sucesso", 39 | copied_to_clipboard: "Copiado para a área de transferência", 40 | // Calendar 41 | price: "Preço", 42 | category: "Categoria", 43 | paid_by: "Pago por", 44 | payment_method: "Método de pagamento", 45 | notes: "Notas", 46 | export: "Exportar", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/ru.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Ошибка перезагрузки подписки:", 4 | error_fetching_image_results: "Ошибка при получении результатов изображения:", 5 | subscription_deleted: "Подписка удалена", 6 | error_deleting_subscription: "Ошибка удаления подписки", 7 | failed_to_load_subscription: "Не удалось загрузить подписку", 8 | edit_subscription: "Изменить подписку", 9 | add_subscription: "Добавить подписку", 10 | confirm_delete_subscription: "Вы уверены, что хотите удалить эту подписку?", 11 | // Settings 12 | network_response_error: "Отсутствует сетевое соединение", 13 | failed_add_member: "Не удалось добавить пользователя", 14 | member: "Пользователь", 15 | email: "Электронная почта", 16 | save_member: "Сохранить пользователя", 17 | delete_member: "Удалить пользователя", 18 | failed_remove_member: "Не удалось удалить пользователя", 19 | failed_save_member: "Не удалось сохранить пользователя", 20 | failed_add_category: "Не удалось добавить категорию", 21 | category: "Категория", 22 | save_category: "Сохранить категорию", 23 | delete_category: "Удалить категорию", 24 | failed_remove_category: "Не удалось удалить категорию", 25 | currency: "Валюта", 26 | currency_code: "Код валюты", 27 | save_currency: "Сохранить валюту", 28 | delete_currency: "Удалить валюту", 29 | failed_remove_currency: "Не удалось удалить валюту.", 30 | failed_save_currency: "Не удалось сохранить валюту.", 31 | cant_disable_payment_in_use: "Невозможно отключить используемый платеж", 32 | failed_save_payment_method: "Не удалось сохранить способ оплаты.", 33 | unknown_error: "Неизвестная ошибка. Повторите попытку.", 34 | error_saving_notification_data: "Ошибка сохранения данных уведомления.", 35 | error_sending_notification: "Ошибка отправки уведомления", 36 | delete_account_confirmation: "Вы уверены, что хотите удалить свою учетную запись?", 37 | this_will_delete_all_data: "Это удалит все ваши данные и не может быть отменено. Продолжить?", 38 | success: "Успешно", 39 | copied_to_clipboard: "Скопировано в буфер обмена", 40 | // Calendar 41 | price: "Цена", 42 | category: "Категория", 43 | paid_by: "Оплачено", 44 | payment_method: "Способ оплаты", 45 | notes: "Примечания", 46 | export: "Экспорт", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/sl.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Napaka pri ponovnem nalaganju naročnine:", 4 | error_fetching_image_results: "Napaka pri pridobivanju rezultatov slik:", 5 | subscription_deleted: "Naročnina je izbrisana", 6 | error_deleting_subscription: "Napaka pri brisanju naročnine", 7 | failed_to_load_subscription: "Nalaganje naročnine ni uspelo", 8 | edit_subscription: "Uredi naročnino", 9 | add_subscription: "Dodaj naročnino", 10 | confirm_delete_subscription: "Ali ste prepričani, da želite izbrisati to naročnino?", 11 | // Settings 12 | network_response_error: "Odziv omrežja ni bil v redu", 13 | failed_add_member: "Dodajanje člana ni uspelo", 14 | member: "Član", 15 | email: "E-pošta", 16 | save_member: "Shrani člana", 17 | delete_member: "Izbriši člana", 18 | failed_remove_member: "Odstranitev člana ni uspela", 19 | failed_save_member: "Člana ni bilo mogoče shraniti", 20 | failed_add_category: "Dodajanje kategorije ni uspelo", 21 | category: "Kategorija", 22 | save_category: "Shrani kategorijo", 23 | delete_category: "Izbriši kategorijo", 24 | failed_remove_category: "Odstranitev kategorije ni uspela", 25 | currency: "Valuta", 26 | currency_code: "Koda valute", 27 | save_currency: "Shrani valuto", 28 | delete_currency: "Izbriši valuto", 29 | failed_remove_currency: "Odstranitev valute ni uspela", 30 | failed_save_currency: "valute ni bilo mogoče shraniti", 31 | cant_disable_payment_in_use: "Plačila v uporabi ni mogoče onemogočiti", 32 | failed_save_payment_method: "Način plačila ni uspel shraniti", 33 | unknown_error: "Neznana napaka, poskusite znova.", 34 | error_saving_notification_data: "Napaka pri shranjevanju obvestilnih podatkov", 35 | error_sending_notification: "Napaka pri pošiljanju obvestila", 36 | delete_account_confirmation: "Ali ste prepričani, da želite izbrisati svoj račun?", 37 | this_will_delete_all_data: "To bo izbrisalo vse vaše podatke in jih ni mogoče obnoviti. Nadaljujem?", 38 | success: "Uspeh", 39 | copied_to_clipboard: "Kopirano v odložišče", 40 | // Calendar 41 | price: "Cena", 42 | category: "Kategorija", 43 | paid_by: "Plačal/a", 44 | payment_method: "Način plačila", 45 | notes: "Opombe", 46 | export: "Izvozi", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/sr.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Грешка при освежавању претплате:", 4 | error_fetching_image_results: "Грешка при преузимању резултата слика:", 5 | subscription_deleted: "Претплата је избрисана", 6 | error_deleting_subscription: "Грешка при брисању претплате", 7 | failed_to_load_subscription: "Неуспешно учитавање претплате", 8 | edit_subscription: "Уреди претплату", 9 | add_subscription: "Додај претплату", 10 | confirm_delete_subscription: "Да ли сте сигурни да желите да избришете ову претплату?", 11 | // Settings 12 | network_response_error: "Мрежни одговор није био у реду", 13 | failed_add_member: "Неуспешно додавање члана", 14 | member: "Члан", 15 | email: "Е-пошта", 16 | save_member: "Сачувај члана", 17 | delete_member: "Избриши члана", 18 | failed_remove_member: "Неуспешно уклањање члана", 19 | failed_save_member: "Неуспешно чување члана", 20 | failed_add_category: "Неуспешно додавање категорије", 21 | category: "Категорија", 22 | save_category: "Сачувај категорију", 23 | delete_category: "Избриши категорију", 24 | failed_remove_category: "Неуспешно уклањање категорије", 25 | currency: "Валута", 26 | currency_code: "Кôд валуте", 27 | save_currency: "Сачувај валуту", 28 | delete_currency: "Избриши валуту", 29 | failed_remove_currency: "Неуспешно уклањање валуте", 30 | failed_save_currency: "Неуспешно чување валуте", 31 | cant_disable_payment_in_use: "Није могуће онемогућити плаћање у употреби", 32 | failed_save_payment_method: "Неуспешно чување начина плаћања", 33 | unknown_error: "Непозната грешка, молимо покушајте поново.", 34 | error_saving_notification_data: "Грешка при чувању података о обавештењима", 35 | error_sending_notification: "Грешка при слању обавештења", 36 | delete_account_confirmation: "Да ли сте сигурни да желите да избришете свој налог?", 37 | this_will_delete_all_data: "Ово ће избрисати све ваше податке и не може се поништити. Настави?", 38 | success: "Успех", 39 | copied_to_clipboard: "Копирано у привремену меморију", 40 | // Calendar 41 | price: "Цена", 42 | category: "Категорија", 43 | paid_by: "Плаћено од стране", 44 | payment_method: "Метод плаћања", 45 | notes: "Белешке", 46 | export: "Извоз", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/sr_lat.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Greška pri osvežavanju pretplate:", 4 | error_fetching_image_results: "Greška pri preuzimanju rezultata slika:", 5 | subscription_deleted: "Pretplata je izbrisana", 6 | error_deleting_subscription: "Greška pri brisanju pretplate", 7 | failed_to_load_subscription: "Neuspešno učitavanje pretplate", 8 | edit_subscription: "Uredi pretplatu", 9 | add_subscription: "Dodaj pretplatu", 10 | confirm_delete_subscription: "Da li ste sigurni da želite da izbrišete ovu pretplatu?", 11 | // Settings 12 | network_response_error: "Mrežni odgovor nije bio u redu", 13 | failed_add_member: "Neuspešno dodavanje člana", 14 | member: "Član", 15 | email: "E-pošta", 16 | save_member: "Sačuvaj člana", 17 | delete_member: "Izbriši člana", 18 | failed_remove_member: "Neuspešno uklanjanje člana", 19 | failed_save_member: "Neuspešno čuvanje člana", 20 | failed_add_category: "Neuspešno dodavanje kategorije", 21 | category: "Kategorija", 22 | save_category: "Sačuvaj kategoriju", 23 | delete_category: "Izbriši kategoriju", 24 | failed_remove_category: "Neuspešno uklanjanje kategorije", 25 | currency: "Valuta", 26 | currency_code: "Kôd valute", 27 | save_currency: "Sačuvaj valutu", 28 | delete_currency: "Izbriši valutu", 29 | failed_remove_currency: "Neuspešno uklanjanje valute", 30 | failed_save_currency: "Neuspešno čuvanje valute", 31 | cant_disable_payment_in_use: "Nije moguće onemogućiti plaćanje u upotrebi", 32 | failed_save_payment_method: "Neuspešno čuvanje načina plaćanja", 33 | unknown_error: "Nepoznata greška, molimo pokušajte ponovo.", 34 | error_saving_notification_data: "Greška pri čuvanju podataka o obaveštenjima", 35 | error_sending_notification: "Greška pri slanju obaveštenja", 36 | delete_account_confirmation: "Da li ste sigurni da želite da izbrišete svoj nalog?", 37 | this_will_delete_all_data: "Ovo će izbrisati sve vaše podatke i ne može se poništiti. Da li nastaviti?", 38 | success: "Uspeh", 39 | copied_to_clipboard: "Kopirano u privremenu memoriju", 40 | // Calendar 41 | price: "Cena", 42 | category: "Kategorija", 43 | paid_by: "Platio/la", 44 | payment_method: "Način plaćanja", 45 | notes: "Beleške", 46 | export: "Izvezi", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/tr.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Abonelik yeniden yüklenirken hata oluştu:", 4 | error_fetching_image_results: "Görüntü sonuçları alınırken hata oluştu:", 5 | subscription_deleted: "Abonelik silindi", 6 | error_deleting_subscription: "Abonelik silinirken hata oluştu", 7 | failed_to_load_subscription: "Abonelik yüklenemedi", 8 | edit_subscription: "Aboneliği Düzenle", 9 | add_subscription: "Abonelik Ekle", 10 | confirm_delete_subscription: "Bu aboneliği silmek istediğinizden emin misiniz?", 11 | // Ayarlar 12 | network_response_error: "Ağ yanıtı kabul edilmedi", 13 | failed_add_member: "Üye eklenemedi", 14 | member: "Üye", 15 | email: "E-posta", 16 | save_member: "Üyeyi Kaydet", 17 | delete_member: "Üyeyi Sil", 18 | failed_remove_member: "Üye silinmedi", 19 | failed_save_member: "Üye kaydedilemedi", 20 | failed_add_category: "Kategori eklenemedi", 21 | category: "Kategori", 22 | save_category: "Kategoriyi Kaydet", 23 | delete_category: "Kategoriyi Sil", 24 | failed_remove_category: "Kategori silinmedi", 25 | currency: "Para Birimi", 26 | currency_code: "Para Birimi Kodu", 27 | save_currency: "Para Birimini Kaydet", 28 | delete_currency: "Para Birimini Sil", 29 | failed_remove_currency: "Para birimi kaldırılamadı", 30 | failed_save_currency: "Para birimi kaydedilemedi", 31 | cant_disable_payment_in_use: "Kullanımdaki ödemeyi devre dışı bırakamazsınız", 32 | failed_save_payment_method: "Ödeme yöntemi kaydedilemedi", 33 | unknown_error: "Bilinmeyen hata, lütfen tekrar deneyin.", 34 | error_saving_notification_data: "Bildirim verisi kaydedilirken hata oluştu", 35 | error_sending_notification: "Bildirim gönderilirken hata oluştu", 36 | delete_account_confirmation: "Hesabınızı silmek istediğinizden emin misiniz?", 37 | this_will_delete_all_data: "Bu tüm verilerinizi silecek ve geri alınamaz. Devam etmek istiyor musunuz?", 38 | success: "Başarılı", 39 | copied_to_clipboard: "Panoya kopyalandı", 40 | // Calendar 41 | price: "Price", 42 | category: "Category", 43 | paid_by: "Paid by", 44 | payment_method: "Payment method", 45 | notes: "Notes", 46 | export: "Export", 47 | } 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /scripts/i18n/vi.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: "Lỗi tải lại đăng ký:", 4 | error_fetching_image_results: "Lỗi khi tìm nạp kết quả hình ảnh:", 5 | subscription_deleted: "Đã xóa đăng ký", 6 | error_deleting_subscription: "Lỗi khi xóa đăng ký", 7 | failed_to_load_subscription: "Không thể tải đăng ký", 8 | edit_subscription: "Chỉnh sửa đăng ký", 9 | add_subscription: "Thêm đăng ký", 10 | confirm_delete_subscription: "Bạn có chắc chắn muốn xóa đăng ký này không?", 11 | // Settings 12 | network_response_error: "Phản hồi mạng không ổn", 13 | failed_add_member: "Không thể thêm thành viên", 14 | member: "Thành viên", 15 | email: "Email", 16 | save_member: "Lưu thành viên", 17 | delete_member: "Xóa thành viên", 18 | failed_remove_member: "Không thể xóa thành viên", 19 | failed_save_member: "Không thể lưu thành viên", 20 | failed_add_category: "Không thể thêm danh mục", 21 | category: "Danh mục", 22 | save_category: "Lưu danh mục", 23 | delete_category: "Xóa danh mục", 24 | failed_remove_category: "Không thể xóa danh mục", 25 | currency: "Tiền tệ", 26 | currency_code: "Mã tiền tệ", 27 | save_currency: "Lưu tiền tệ", 28 | delete_currency: "Xóa tiền tệ", 29 | failed_remove_currency: "Không thể xóa tiền tệ", 30 | failed_save_currency: "Không thể lưu tiền tệ", 31 | cant_disable_payment_in_use: "Không thể vô hiệu hóa phương thức thanh toán đang được sử dụng", 32 | failed_save_payment_method: "Không thể lưu phương thức thanh toán", 33 | unknown_error: "Lỗi không xác định, vui lòng thử lại.", 34 | error_saving_notification_data: "Lỗi khi lưu dữ liệu thông báo", 35 | error_sending_notification: "Lỗi khi gửi thông báo", 36 | delete_account_confirmation: "Bạn có chắc chắn muốn xóa tài khoản của mình không?", 37 | this_will_delete_all_data: "Điều này sẽ xóa tất cả dữ liệu của bạn và không thể hoàn tác. Tiếp tục?", 38 | success: "Thành công", 39 | copied_to_clipboard: "Đã sao chép vào bảng tạm", 40 | // Calendar 41 | price: "Giá", 42 | category: "Danh mục", 43 | paid_by: "Người thanh toán", 44 | payment_method: "Phương thức thanh toán", 45 | notes: "Ghi chú", 46 | export: "Xuất", 47 | } 48 | -------------------------------------------------------------------------------- /scripts/i18n/zh_cn.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | 'error_reloading_subscription': '重新加载订阅时出错:', 4 | 'error_fetching_image_results': '获取图片结果时出错:', 5 | 'subscription_deleted': '订阅已删除', 6 | 'error_deleting_subscription': "删除订阅时出错", 7 | 'failed_to_load_subscription': "加载订阅失败", 8 | 'edit_subscription': "编辑订阅", 9 | 'add_subscription': "添加订阅", 10 | 'confirm_delete_subscription': "您确定要删除此订阅吗?", 11 | // Settings 12 | 'network_response_error': "网络响应不正常", 13 | 'failed_add_member': '添加成员失败', 14 | 'member': '成员', 15 | 'email': '电子邮箱', 16 | 'save_member': '保存成员', 17 | 'delete_member': '删除成员', 18 | 'failed_remove_member': '移除成员失败', 19 | 'failed_save_member': '保存成员失败', 20 | 'failed_add_category': '添加类别失败', 21 | 'category': '类别', 22 | 'save_category': '保存类别', 23 | 'delete_category': '删除类别', 24 | 'failed_remove_category': '移除类别失败', 25 | 'currency': '货币', 26 | 'currency_code': '货币代码', 27 | 'save_currency': '保存货币', 28 | 'delete_currency': '删除货币', 29 | 'failed_remove_currency': '移除货币失败', 30 | 'failed_save_currency': '保存货币失败', 31 | 'cant_disable_payment_in_use': '无法禁用正在使用的支付方式', 32 | 'failed_save_payment_method': '保存支付方式失败', 33 | 'unknown_error': '未知错误,请重试。', 34 | 'error_saving_notification_data': '保存通知数据时出错', 35 | 'error_sending_notification': '发送通知时出错', 36 | 'delete_account_confirmation': "您确定要删除您的帐户吗?", 37 | 'this_will_delete_all_data': "这将删除所有您的数据,且无法撤销。是否继续?", 38 | 'success': "成功", 39 | 'copied_to_clipboard': "已复制到剪贴板", 40 | // Calendar 41 | price: "价格", 42 | category: "类别", 43 | paid_by: "支付者", 44 | payment_method: "支付方式", 45 | notes: "备注", 46 | export: "导出", 47 | }; 48 | -------------------------------------------------------------------------------- /scripts/i18n/zh_tw.js: -------------------------------------------------------------------------------- 1 | let i18n = { 2 | // Dashboard 3 | error_reloading_subscription: '重新讀取訂閱時發生錯誤:', 4 | error_fetching_image_results: '抓取圖片時發生錯誤:', 5 | subscription_deleted: '訂閱已刪除', 6 | error_deleting_subscription: "刪除訂閱時發生錯誤", 7 | failed_to_load_subscription: "讀取訂閱失敗", 8 | edit_subscription: "編輯訂閱", 9 | add_subscription: "新增訂閱", 10 | confirm_delete_subscription: "您確定要刪除此訂閱嗎?", 11 | // Settings 12 | network_response_error: "網路無回應", 13 | failed_add_member: '新增成員失敗', 14 | member: '成員', 15 | email: '電子信箱', 16 | save_member: '保存成員', 17 | delete_member: '刪除成員', 18 | failed_remove_member: '移除成員失敗', 19 | failed_save_member: '保存成員失敗', 20 | failed_add_category: '新增類別失敗', 21 | category: '類別', 22 | save_category: '保存類別', 23 | delete_category: '刪除類別', 24 | failed_remove_category: '移除類別失敗', 25 | currency: '貨幣', 26 | currency_code: '貨幣代碼', 27 | save_currency: '保存貨幣', 28 | delete_currency: '刪除貨幣', 29 | failed_remove_currency: '移除貨幣失敗', 30 | failed_save_currency: '保存貨幣失敗', 31 | cant_disable_payment_in_use: '無法停用正在使用中的支付方式', 32 | failed_save_payment_method: '保存支付方式失敗', 33 | unknown_error: '發生未知的錯誤,請再試一次。', 34 | error_saving_notification_data: '保存通知資料時發生錯誤', 35 | error_sending_notification: '發送通知時發生錯誤', 36 | delete_account_confirmation: "您確定要刪除您的帳戶嗎?", 37 | this_will_delete_all_data: "這將刪除所有資料,且無法復原。繼續?", 38 | success: "成功", 39 | copied_to_clipboard: "已複製到剪貼簿", 40 | // Calendar 41 | price: "價格", 42 | category: "類別", 43 | paid_by: "支付者", 44 | payment_method: "支付方式", 45 | notes: "備註", 46 | export: "匯出", 47 | }; 48 | -------------------------------------------------------------------------------- /scripts/login.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function () { 2 | 3 | const userLocale = navigator.language || navigator.languages[0]; 4 | document.cookie = `user_locale=${userLocale}; expires=Fri, 31 Dec 9999 23:59:59 GMT; SameSite=Strict`; 5 | 6 | if (window.update_theme_settings) { 7 | const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; 8 | const themePreference = prefersDarkMode ? 'dark' : 'light'; 9 | const darkThemeCss = document.querySelector("#dark-theme"); 10 | darkThemeCss.disabled = themePreference === 'light'; 11 | document.body.className = themePreference; 12 | const themeColorMetaTag = document.querySelector('meta[name="theme-color"]'); 13 | themeColorMetaTag.setAttribute('content', themePreference === 'dark' ? '#222222' : '#FFFFFF'); 14 | } 15 | 16 | }); -------------------------------------------------------------------------------- /startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Startup script is running..." > /var/log/startup.log 4 | 5 | # Default the PUID and PGID environment variables to 82, otherwise 6 | # set to the user defined ones. 7 | PUID=${PUID:-82} 8 | PGID=${PGID:-82} 9 | 10 | # Change the www-data user id and group id to be the user-specified ones 11 | groupmod -o -g "$PGID" www-data 12 | usermod -o -u "$PUID" www-data 13 | chown -R www-data:www-data /var/www/html 14 | chown -R www-data:www-data /tmp 15 | chmod -R 770 /tmp 16 | 17 | # Start both PHP-FPM and Nginx 18 | php-fpm & nginx -g 'daemon off;' & touch ~/startup.txt 19 | 20 | # Start the cron daemon 21 | crond 22 | 23 | # Wait one second before running scripts 24 | sleep 1 25 | 26 | # Create database if it does not exist 27 | /usr/local/bin/php /var/www/html/endpoints/cronjobs/createdatabase.php 28 | 29 | # Perform any database migrations 30 | /usr/local/bin/php /var/www/html/endpoints/db/migrate.php 31 | 32 | # Change permissions on the database directory 33 | chmod -R 755 /var/www/html/db/ 34 | chown -R www-data:www-data /var/www/html/db/ 35 | 36 | mkdir -p /var/www/html/images/uploads/logos/avatars 37 | 38 | # Change permissions on the logos directory 39 | chmod -R 755 /var/www/html/images/uploads/logos 40 | chown -R www-data:www-data /var/www/html/images/uploads/logos 41 | 42 | # Remove crontab for the user 43 | crontab -d -u root 44 | 45 | # Run updatenextpayment.php and wait for it to finish 46 | /usr/local/bin/php /var/www/html/endpoints/cronjobs/updatenextpayment.php 47 | 48 | # Run updateexchange.php 49 | /usr/local/bin/php /var/www/html/endpoints/cronjobs/updateexchange.php 50 | 51 | # Run checkforupdates.php 52 | /usr/local/bin/php /var/www/html/endpoints/cronjobs/checkforupdates.php 53 | 54 | # Keep the container running indefinitely (this won't exit) 55 | tail -f /dev/null -------------------------------------------------------------------------------- /styles/login-dark-theme.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #303030; 3 | color: #E0E0E0; 4 | } 5 | 6 | svg .text-color { 7 | fill: #E0E0E0; 8 | } 9 | 10 | .container { 11 | background-color: #222; 12 | border: 1px solid #333; 13 | box-shadow: 0 2px 5px rgba(255, 255, 255, 0.1); 14 | } 15 | 16 | @media (max-width: 768px) { 17 | .container { 18 | background-color: transparent; 19 | border: none; 20 | box-shadow: none; 21 | } 22 | } 23 | 24 | input[type="text"], 25 | input[type="email"], 26 | input[type="password"], 27 | input[type="checkbox"], 28 | select { 29 | background-color: #555; 30 | border: 1px solid #666; 31 | color: #E0E0E0; 32 | } 33 | 34 | input[type="text"]::placeholder, 35 | input[type="email"]::placeholder, 36 | input[type="password"]::placeholder { 37 | color: #BBB; 38 | } -------------------------------------------------------------------------------- /styles/theme.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --main-color: #007bff; 3 | --main-color-rgb: 0, 123, 255; 4 | --accent-color: #8fbffa; 5 | --accent-color-rgb: 143, 191, 250; 6 | --hover-color: #0056b3; 7 | --hover-color-rgb: 0, 86, 179; 8 | --error-color: #f45a40; 9 | --error-color-rgb: 244, 90, 64; 10 | --success-color: #188823; 11 | --success-color-rgb: 24, 136, 35; 12 | } 13 | 14 | svg .main-color { 15 | fill: var(--main-color); 16 | } 17 | 18 | svg .accent-color { 19 | fill: var(--accent-color); 20 | } 21 | 22 | svg .text-color { 23 | fill: #202020; 24 | } -------------------------------------------------------------------------------- /styles/themes/green.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --main-color: #6B8E23; /* Dark Olive Green */ 3 | --main-color-rgb: 107, 142, 35; 4 | --accent-color: #9ACD32; /* Yellow-Green */ 5 | --accent-color-rgb: 154, 205, 50; 6 | --hover-color: #556B2F; /* Olive Drab */ 7 | --hover-color-rgb: 85, 107, 47; 8 | } -------------------------------------------------------------------------------- /styles/themes/purple.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --main-color: #6d4aff; 3 | --main-color-rgb: 109, 74, 255; 4 | --accent-color: #b086ff; 5 | --accent-color-rgb: 176, 134, 255; 6 | --hover-color: #5e42cd; 7 | --hover-color-rgb: 50, 48, 108; 8 | } 9 | -------------------------------------------------------------------------------- /styles/themes/red.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --main-color: #f45a40; 3 | --main-color-rgb: 244, 90, 64; 4 | --accent-color: #f79988; 5 | --accent-color-rgb: 239, 134, 116; 6 | --hover-color: #c73f29; 7 | --hover-color-rgb: 199, 63, 41; 8 | } 9 | -------------------------------------------------------------------------------- /styles/themes/yellow.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --main-color: #ffae00; 3 | --main-color-rgb: 255, 174, 0; 4 | --accent-color: #faea8f; 5 | --accent-color-rgb: 250, 234, 143; 6 | --hover-color: #cd930c; 7 | --hover-color-rgb: 179, 124, 0; 8 | } -------------------------------------------------------------------------------- /webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ellite/Wallos/a7e26f688a00101bda85606d59cdd500d1cd6970/webfonts/fa-solid-900.woff2 --------------------------------------------------------------------------------