diff --git a/.forgejo/workflows/build-on-commit.yml b/.forgejo/workflows/build-on-commit.yml deleted file mode 100644 index e8f0d2e3..00000000 --- a/.forgejo/workflows/build-on-commit.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Build Docker Image on Commit - -on: - push: - branches: - - main - tags: - - '!' # Exclude tags - -jobs: - build-and-publish: - runs-on: docker-builder - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set REPO_VARS - id: repo-url - run: | - echo "REPO_HOST=$(echo "${{ github.server_url }}" | sed 's~http[s]*://~~g')" >> $GITHUB_ENV - echo "REPO_PATH=${{ github.repository }}" >> $GITHUB_ENV - - - name: Login to OCI registry - run: | - echo "${{ secrets.OCI_TOKEN }}" | docker login $REPO_HOST -u "${{ secrets.OCI_USER }}" --password-stdin - - - name: Build and push Docker images - run: | - # Build Docker image with commit SHA - docker build -t $REPO_HOST/$REPO_PATH:${{ github.sha }} . - docker push $REPO_HOST/$REPO_PATH:${{ github.sha }} - - # Build Docker image with nightly tag - docker tag $REPO_HOST/$REPO_PATH:${{ github.sha }} $REPO_HOST/$REPO_PATH:nightly - docker push $REPO_HOST/$REPO_PATH:nightly - - # Remove local images to save storage - docker rmi $REPO_HOST/$REPO_PATH:${{ github.sha }} - docker rmi $REPO_HOST/$REPO_PATH:nightly diff --git a/.forgejo/workflows/build-on-tag.yml b/.forgejo/workflows/build-on-tag.yml deleted file mode 100644 index 888102b6..00000000 --- a/.forgejo/workflows/build-on-tag.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Build and Publish Docker Image on Tag - -on: - push: - tags: - - '*' - -jobs: - build-and-publish: - runs-on: docker-builder - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set REPO_VARS - id: repo-url - run: | - echo "REPO_HOST=$(echo "${{ github.server_url }}" | sed 's~http[s]*://~~g')" >> $GITHUB_ENV - echo "REPO_PATH=${{ github.repository }}" >> $GITHUB_ENV - - - name: Login to OCI registry - run: | - echo "${{ secrets.OCI_TOKEN }}" | docker login $REPO_HOST -u "${{ secrets.OCI_USER }}" --password-stdin - - - name: Build and push Docker image - run: | - TAG=${{ github.ref_name }} # Get the tag name from the context - # Build and push multi-platform Docker images - docker build -t $REPO_HOST/$REPO_PATH:$TAG --push . - # Tag and push latest - docker tag $REPO_HOST/$REPO_PATH:$TAG $REPO_HOST/$REPO_PATH:latest - docker push $REPO_HOST/$REPO_PATH:latest - - # Remove the local image to save storage - docker rmi $REPO_HOST/$REPO_PATH:$TAG - docker rmi $REPO_HOST/$REPO_PATH:latest \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index aab991d5..8c9f6621 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,10 +1 @@ -github: canewsin -patreon: # Replace with a single Patreon username e.g., user1 -open_collective: # Replace with a single Open Collective username e.g., user1 -ko_fi: canewsin -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: canewsin -issuehunt: # Replace with a single IssueHunt username e.g., user1 -otechie: # Replace with a single Otechie username e.g., user1 -custom: ['https://paypal.me/PramUkesh', 'https://zerolink.ml/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/help_zeronet/donate/'] +custom: https://zerolink.ml/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/help_zeronet/donate/ diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 27b5c924..00000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,72 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ py3-latest ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ py3-latest ] - schedule: - - cron: '32 19 * * 2' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'javascript', 'python' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2bdcaf95..6eaf3c6b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,48 +4,49 @@ on: [push, pull_request] jobs: test: - runs-on: ubuntu-20.04 + + runs-on: ubuntu-18.04 strategy: max-parallel: 16 matrix: - python-version: ["3.7", "3.8", "3.9"] + python-version: [3.6, 3.7, 3.8, 3.9] steps: - - name: Checkout ZeroNet - uses: actions/checkout@v2 - with: - submodules: "true" + - name: Checkout ZeroNet + uses: actions/checkout@v2 + with: + submodules: 'true' - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} - - name: Prepare for installation - run: | - python3 -m pip install setuptools - python3 -m pip install --upgrade pip wheel - python3 -m pip install --upgrade codecov coveralls flake8 mock pytest==4.6.3 pytest-cov selenium + - name: Prepare for installation + run: | + python3 -m pip install setuptools + python3 -m pip install --upgrade pip wheel + python3 -m pip install --upgrade codecov coveralls flake8 mock pytest==4.6.3 pytest-cov selenium - - name: Install - run: | - python3 -m pip install --upgrade -r requirements.txt - python3 -m pip list + - name: Install + run: | + python3 -m pip install --upgrade -r requirements.txt + python3 -m pip list - - name: Prepare for tests - run: | - openssl version -a - echo 0 | sudo tee /proc/sys/net/ipv6/conf/all/disable_ipv6 + - name: Prepare for tests + run: | + openssl version -a + echo 0 | sudo tee /proc/sys/net/ipv6/conf/all/disable_ipv6 - - name: Test - run: | - catchsegv python3 -m pytest src/Test --cov=src --cov-config src/Test/coverage.ini - export ZERONET_LOG_DIR="log/CryptMessage"; catchsegv python3 -m pytest -x plugins/CryptMessage/Test - export ZERONET_LOG_DIR="log/Bigfile"; catchsegv python3 -m pytest -x plugins/Bigfile/Test - export ZERONET_LOG_DIR="log/AnnounceLocal"; catchsegv python3 -m pytest -x plugins/AnnounceLocal/Test - export ZERONET_LOG_DIR="log/OptionalManager"; catchsegv python3 -m pytest -x plugins/OptionalManager/Test - export ZERONET_LOG_DIR="log/Multiuser"; mv plugins/disabled-Multiuser plugins/Multiuser && catchsegv python -m pytest -x plugins/Multiuser/Test - export ZERONET_LOG_DIR="log/Bootstrapper"; mv plugins/disabled-Bootstrapper plugins/Bootstrapper && catchsegv python -m pytest -x plugins/Bootstrapper/Test - find src -name "*.json" | xargs -n 1 python3 -c "import json, sys; print(sys.argv[1], end=' '); json.load(open(sys.argv[1])); print('[OK]')" - find plugins -name "*.json" | xargs -n 1 python3 -c "import json, sys; print(sys.argv[1], end=' '); json.load(open(sys.argv[1])); print('[OK]')" - flake8 . --count --select=E9,F63,F72,F82 --show-source --statistics --exclude=src/lib/pyaes/ + - name: Test + run: | + catchsegv python3 -m pytest src/Test --cov=src --cov-config src/Test/coverage.ini + export ZERONET_LOG_DIR="log/CryptMessage"; catchsegv python3 -m pytest -x plugins/CryptMessage/Test + export ZERONET_LOG_DIR="log/Bigfile"; catchsegv python3 -m pytest -x plugins/Bigfile/Test + export ZERONET_LOG_DIR="log/AnnounceLocal"; catchsegv python3 -m pytest -x plugins/AnnounceLocal/Test + export ZERONET_LOG_DIR="log/OptionalManager"; catchsegv python3 -m pytest -x plugins/OptionalManager/Test + export ZERONET_LOG_DIR="log/Multiuser"; mv plugins/disabled-Multiuser plugins/Multiuser && catchsegv python -m pytest -x plugins/Multiuser/Test + export ZERONET_LOG_DIR="log/Bootstrapper"; mv plugins/disabled-Bootstrapper plugins/Bootstrapper && catchsegv python -m pytest -x plugins/Bootstrapper/Test + find src -name "*.json" | xargs -n 1 python3 -c "import json, sys; print(sys.argv[1], end=' '); json.load(open(sys.argv[1])); print('[OK]')" + find plugins -name "*.json" | xargs -n 1 python3 -c "import json, sys; print(sys.argv[1], end=' '); json.load(open(sys.argv[1])); print('[OK]')" + flake8 . --count --select=E9,F63,F72,F82 --show-source --statistics --exclude=src/lib/pyaes/ diff --git a/.gitignore b/.gitignore index 636cd115..38dd3a34 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ __pycache__/ # Hidden files .* -!/.forgejo !/.github !/.gitignore !/.travis.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 6974d18a..b49b9ef6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,85 +1,6 @@ -### ZeroNet 0.9.0 (2023-07-12) Rev4630 - - Fix RDos Issue in Plugins https://github.com/ZeroNetX/ZeroNet-Plugins/pull/9 - - Add trackers to Config.py for failsafety incase missing trackers.txt - - Added Proxy links - - Fix pysha3 dep installation issue - - FileRequest -> Remove Unnecessary check, Fix error wording - - Fix Response when site is missing for `actionAs` +### ZeroNet 0.7.2 (2020-09-?) Rev4206? -### ZeroNet 0.8.5 (2023-02-12) Rev4625 - - Fix(https://github.com/ZeroNetX/ZeroNet/pull/202) for SSL cert gen failed on Windows. - - default theme-class for missing value in `users.json`. - - Fetch Stats Plugin changes. - -### ZeroNet 0.8.4 (2022-12-12) Rev4620 - - Increase Minimum Site size to 25MB. - -### ZeroNet 0.8.3 (2022-12-11) Rev4611 - - main.py -> Fix accessing unassigned varible - - ContentManager -> Support for multiSig - - SiteStrorage.py -> Fix accessing unassigned varible - - ContentManager.py Improve Logging of Valid Signers - -### ZeroNet 0.8.2 (2022-11-01) Rev4610 - - Fix Startup Error when plugins dir missing - - Move trackers to seperate file & Add more trackers - - Config:: Skip loading missing tracker files - - Added documentation for getRandomPort fn - -### ZeroNet 0.8.1 (2022-10-01) Rev4600 - - fix readdress loop (cherry-pick previously added commit from conservancy) - - Remove Patreon badge - - Update README-ru.md (#177) - - Include inner_path of failed request for signing in error msg and response - - Don't Fail Silently When Cert is Not Selected - - Console Log Updates, Specify min supported ZeroNet version for Rust version Protocol Compatibility - - Update FUNDING.yml - -### ZeroNet 0.8.0 (2022-05-27) Rev4591 - - Revert File Open to catch File Access Errors. - -### ZeroNet 0.7.9-patch (2022-05-26) Rev4586 - - Use xescape(s) from zeronet-conservancy - - actionUpdate response Optimisation - - Fetch Plugins Repo Updates - - Fix Unhandled File Access Errors - - Create codeql-analysis.yml - -### ZeroNet 0.7.9 (2022-05-26) Rev4585 - - Rust Version Compatibility for update Protocol msg - - Removed Non Working Trakers. - - Dynamically Load Trackers from Dashboard Site. - - Tracker Supply Improvements. - - Fix Repo Url for Bug Report - - First Party Tracker Update Service using Dashboard Site. - - remove old v2 onion service [#158](https://github.com/ZeroNetX/ZeroNet/pull/158) - -### ZeroNet 0.7.8 (2022-03-02) Rev4580 - - Update Plugins with some bug fixes and Improvements - -### ZeroNet 0.7.6 (2022-01-12) Rev4565 - - Sync Plugin Updates - - Clean up tor v3 patch [#115](https://github.com/ZeroNetX/ZeroNet/pull/115) - - Add More Default Plugins to Repo - - Doubled Site Publish Limits - - Update ZeroNet Repo Urls [#103](https://github.com/ZeroNetX/ZeroNet/pull/103) - - UI/UX: Increases Size of Notifications Close Button [#106](https://github.com/ZeroNetX/ZeroNet/pull/106) - - Moved Plugins to Seperate Repo - - Added `access_key` variable in Config, this used to access restrited plugins when multiuser plugin is enabled. When MultiUserPlugin is enabled we cannot access some pages like /Stats, this key will remove such restriction with access key. - - Added `last_connection_id_current_version` to ConnectionServer, helpful to estimate no of connection from current client version. - - Added current version: connections to /Stats page. see the previous point. - -### ZeroNet 0.7.5 (2021-11-28) Rev4560 - - Add more default trackers - - Change default homepage address to `1HELLoE3sFD9569CLCbHEAVqvqV7U2Ri9d` - - Change default update site address to `1Update8crprmciJHwp2WXqkx2c4iYp18` - -### ZeroNet 0.7.3 (2021-11-28) Rev4555 - - Fix xrange is undefined error - - Fix Incorrect viewport on mobile while loading - - Tor-V3 Patch by anonymoose - ### ZeroNet 0.7.1 (2019-07-01) Rev4206 ### Added diff --git a/README-ru.md b/README-ru.md index 7d557727..1d0bafc1 100644 --- a/README-ru.md +++ b/README-ru.md @@ -3,131 +3,206 @@ [简体中文](./README-zh-cn.md) [English](./README.md) -Децентрализованные вебсайты, использующие криптографию Bitcoin и протокол BitTorrent — https://zeronet.dev ([Зеркало в ZeroNet](http://127.0.0.1:43110/1ZeroNetyV5mKY9JF1gsm82TuBXHpfdLX/)). В отличии от Bitcoin, ZeroNet'у не требуется блокчейн для работы, однако он использует ту же криптографию, чтобы обеспечить сохранность и проверку данных. +Децентрализованные вебсайты использующие Bitcoin криптографию и BitTorrent сеть - https://zeronet.dev + ## Зачем? -- Мы верим в открытую, свободную, и неподдающуюся цензуре сеть и связь. -- Нет единой точки отказа: Сайт остаётся онлайн, пока его обслуживает хотя бы 1 пир. -- Нет затрат на хостинг: Сайты обслуживаются посетителями. -- Невозможно отключить: Он нигде, потому что он везде. -- Скорость и возможность работать без Интернета: Вы сможете получить доступ к сайту, потому что его копия хранится на вашем компьютере и у ваших пиров. +* Мы верим в открытую, свободную, и не отцензуренную сеть и коммуникацию. +* Нет единой точки отказа: Сайт онлайн пока по крайней мере 1 пир обслуживает его. +* Никаких затрат на хостинг: Сайты обслуживаются посетителями. +* Невозможно отключить: Он нигде, потому что он везде. +* Быстр и работает оффлайн: Вы можете получить доступ к сайту, даже если Интернет недоступен. + ## Особенности + * Обновляемые в реальном времени сайты + * Поддержка Namecoin .bit доменов + * Лёгок в установке: распаковал & запустил + * Клонирование вебсайтов в один клик + * Password-less [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) + based authorization: Ваша учетная запись защищена той же криптографией, что и ваш Bitcoin-кошелек + * Встроенный SQL-сервер с синхронизацией данных P2P: Позволяет упростить разработку сайта и ускорить загрузку страницы + * Анонимность: Полная поддержка сети Tor с помощью скрытых служб .onion вместо адресов IPv4 + * TLS зашифрованные связи + * Автоматическое открытие uPnP порта + * Плагин для поддержки многопользовательской (openproxy) + * Работает с любыми браузерами и операционными системами -- Обновление сайтов в реальном времени -- Поддержка доменов `.bit` ([Namecoin](https://www.namecoin.org)) -- Легкая установка: просто распакуйте и запустите -- Клонирование сайтов "в один клик" -- Беспарольная [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) - авторизация: Ваша учетная запись защищена той же криптографией, что и ваш Bitcoin-кошелек -- Встроенный SQL-сервер с синхронизацией данных P2P: Позволяет упростить разработку сайта и ускорить загрузку страницы -- Анонимность: Полная поддержка сети Tor, используя скрытые службы `.onion` вместо адресов IPv4 -- Зашифрованное TLS подключение -- Автоматическое открытие UPnP–порта -- Плагин для поддержки нескольких пользователей (openproxy) -- Работа с любыми браузерами и операционными системами - -## Текущие ограничения - -- Файловые транзакции не сжаты -- Нет приватных сайтов ## Как это работает? -- После запуска `zeronet.py` вы сможете посещать сайты в ZeroNet, используя адрес - `http://127.0.0.1:43110/{zeronet_адрес}` - (Например: `http://127.0.0.1:43110/1HELLoE3sFD9569CLCbHEAVqvqV7U2Ri9d`). -- Когда вы посещаете новый сайт в ZeroNet, он пытается найти пиров с помощью протокола BitTorrent, - чтобы скачать у них файлы сайта (HTML, CSS, JS и т.д.). -- После посещения сайта вы тоже становитесь его пиром. -- Каждый сайт содержит файл `content.json`, который содержит SHA512 хеши всех остальные файлы - и подпись, созданную с помощью закрытого ключа сайта. -- Если владелец сайта (тот, кто владеет закрытым ключом для адреса сайта) изменяет сайт, он +* После запуска `zeronet.py` вы сможете посетить зайты (zeronet сайты) используя адрес + `http://127.0.0.1:43110/{zeronet_address}` +(например. `http://127.0.0.1:43110/1HELLoE3sFD9569CLCbHEAVqvqV7U2Ri9d`). +* Когда вы посещаете новый сайт zeronet, он пытается найти пиров с помощью BitTorrent + чтобы загрузить файлы сайтов (html, css, js ...) из них. +* Каждый посещенный зайт также обслуживается вами. (Т.е хранится у вас на компьютере) +* Каждый сайт содержит файл `content.json`, который содержит все остальные файлы в хэше sha512 + и подпись, созданную с использованием частного ключа сайта. +* Если владелец сайта (у которого есть закрытый ключ для адреса сайта) изменяет сайт, то он/она подписывает новый `content.json` и публикует его для пиров. После этого пиры проверяют целостность `content.json` - (используя подпись), скачвают изменённые файлы и распространяют новый контент для других пиров. + (используя подпись), они загружают измененные файлы и публикуют новый контент для других пиров. + +#### [Слайд-шоу о криптографии ZeroNet, обновлениях сайтов, многопользовательских сайтах »](https://docs.google.com/presentation/d/1_2qK1IuOKJ51pgBvllZ9Yu7Au2l551t3XBgyTSvilew/pub?start=false&loop=false&delayms=3000) +#### [Часто задаваемые вопросы »](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/faq/) + +#### [Документация разработчика ZeroNet »](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/site_development/getting_started/) -[Презентация о криптографии ZeroNet, обновлениях сайтов, многопользовательских сайтах »](https://docs.google.com/presentation/d/1_2qK1IuOKJ51pgBvllZ9Yu7Au2l551t3XBgyTSvilew/pub?start=false&loop=false&delayms=3000) -[Часто задаваемые вопросы »](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/faq/) -[Документация разработчика ZeroNet »](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/site_development/getting_started/) ## Скриншоты ![Screenshot](https://i.imgur.com/H60OAHY.png) ![ZeroTalk](https://zeronet.io/docs/img/zerotalk.png) -[Больше скриншотов в документации ZeroNet »](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/using_zeronet/sample_sites/) -## Как присоединиться? +#### [Больше скриншотов в ZeroNet документации »](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/using_zeronet/sample_sites/) -### Windows -- Скачайте и распакуйте архив [ZeroNet-win.zip](https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-win.zip) (26МБ) -- Запустите `ZeroNet.exe` +## Как вступить -### macOS +* Скачайте ZeroBundle пакет: + * [Microsoft Windows](https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-win.zip) + * [Apple macOS](https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-mac.zip) + * [Linux 64-bit](https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-linux.zip) + * [Linux 32-bit](https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-linux.zip) +* Распакуйте где угодно +* Запустите `ZeroNet.exe` (win), `ZeroNet(.app)` (osx), `ZeroNet.sh` (linux) -- Скачайте и распакуйте архив [ZeroNet-mac.zip](https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-mac.zip) (14МБ) -- Запустите `ZeroNet.app` +### Linux терминал -### Linux (64 бит) +* `wget https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-linux.zip` +* `unzip ZeroNet-linux.zip` +* `cd ZeroNet-linux` +* Запустите с помощью `./ZeroNet.sh` -- Скачайте и распакуйте архив [ZeroNet-linux.zip](https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-linux.zip) (14МБ) -- Запустите `./ZeroNet.sh` +Он загружает последнюю версию ZeroNet, затем запускает её автоматически. -> **Note** -> Запустите таким образом: `./ZeroNet.sh --ui_ip '*' --ui_restrict ваш_ip_адрес`, чтобы разрешить удалённое подключение к веб–интерфейсу. +#### Ручная установка для Debian Linux -### Docker +* `wget https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-src.zip` +* `unzip ZeroNet-src.zip` +* `cd ZeroNet` +* `sudo apt-get update` +* `sudo apt-get install python3-pip` +* `sudo python3 -m pip install -r requirements.txt` +* Запустите с помощью `python3 zeronet.py` +* Откройте http://127.0.0.1:43110/ в вашем браузере. -Официальный образ находится здесь: https://hub.docker.com/r/canewsin/zeronet/ +### [Arch Linux](https://www.archlinux.org) -### Android (arm, arm64, x86) +* `git clone https://aur.archlinux.org/zeronet.git` +* `cd zeronet` +* `makepkg -srci` +* `systemctl start zeronet` +* Откройте http://127.0.0.1:43110/ в вашем браузере. -- Для работы требуется Android как минимум версии 5.0 Lollipop -- [Download from Google Play](https://play.google.com/store/apps/details?id=in.canews.zeronetmobile) -- Скачать APK: https://github.com/canewsin/zeronet_mobile/releases +Смотрите [ArchWiki](https://wiki.archlinux.org)'s [ZeroNet +article](https://wiki.archlinux.org/index.php/ZeroNet) для дальнейшей помощи. -### Android (arm, arm64, x86) Облегчённый клиент только для просмотра (1МБ) +### [Gentoo Linux](https://www.gentoo.org) -- Для работы требуется Android как минимум версии 4.1 Jelly Bean -- [Download from Google Play](https://play.google.com/store/apps/details?id=dev.zeronetx.app.lite) +* [`layman -a raiagent`](https://github.com/leycec/raiagent) +* `echo '>=net-vpn/zeronet-0.5.4' >> /etc/portage/package.accept_keywords` +* *(Опционально)* Включить поддержку Tor: `echo 'net-vpn/zeronet tor' >> + /etc/portage/package.use` +* `emerge zeronet` +* `rc-service zeronet start` +* Откройте http://127.0.0.1:43110/ в вашем браузере. -### Установка из исходного кода +Смотрите `/usr/share/doc/zeronet-*/README.gentoo.bz2` для дальнейшей помощи. -```sh -wget https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-src.zip -unzip ZeroNet-src.zip -cd ZeroNet -sudo apt-get update -sudo apt-get install python3-pip -sudo python3 -m pip install -r requirements.txt +### [FreeBSD](https://www.freebsd.org/) + +* `pkg install zeronet` or `cd /usr/ports/security/zeronet/ && make install clean` +* `sysrc zeronet_enable="YES"` +* `service zeronet start` +* Откройте http://127.0.0.1:43110/ в вашем браузере. + +### [Vagrant](https://www.vagrantup.com/) + +* `vagrant up` +* Подключитесь к VM с помощью `vagrant ssh` +* `cd /vagrant` +* Запустите `python3 zeronet.py --ui_ip 0.0.0.0` +* Откройте http://127.0.0.1:43110/ в вашем браузере. + +### [Docker](https://www.docker.com/) +* `docker run -d -v :/root/data -p 15441:15441 -p 127.0.0.1:43110:43110 canewsin/zeronet` +* Это изображение Docker включает в себя прокси-сервер Tor, который по умолчанию отключён. + Остерегайтесь что некоторые хостинг-провайдеры могут не позволить вам запускать Tor на своих серверах. + Если вы хотите включить его,установите переменную среды `ENABLE_TOR` в` true` (по умолчанию: `false`) Например: + + `docker run -d -e "ENABLE_TOR=true" -v :/root/data -p 15441:15441 -p 127.0.0.1:43110:43110 canewsin/zeronet` +* Откройте http://127.0.0.1:43110/ в вашем браузере. + +### [Virtualenv](https://virtualenv.readthedocs.org/en/latest/) + +* `virtualenv env` +* `source env/bin/activate` +* `pip install msgpack gevent` +* `python3 zeronet.py` +* Откройте http://127.0.0.1:43110/ в вашем браузере. + +## Текущие ограничения + +* Файловые транзакции не сжаты +* Нет приватных сайтов + + +## Как я могу создать сайт в Zeronet? + +Завершите работу zeronet, если он запущен + +```bash +$ zeronet.py siteCreate +... +- Site private key (Приватный ключ сайта): 23DKQpzxhbVBrAtvLEc2uvk7DZweh4qL3fn3jpM3LgHDczMK2TtYUq +- Site address (Адрес сайта): 13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2 +... +- Site created! (Сайт создан) +$ zeronet.py +... ``` -- Запустите `python3 zeronet.py` -Откройте приветственную страницу ZeroHello в вашем браузере по ссылке http://127.0.0.1:43110/ +Поздравляем, вы закончили! Теперь каждый может получить доступ к вашему зайту используя +`http://localhost:43110/13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2` -## Как мне создать сайт в ZeroNet? +Следующие шаги: [ZeroNet Developer Documentation](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/site_development/getting_started/) -- Кликните на **⋮** > **"Create new, empty site"** в меню на сайте [ZeroHello](http://127.0.0.1:43110/1HELLoE3sFD9569CLCbHEAVqvqV7U2Ri9d). -- Вы будете **перенаправлены** на совершенно новый сайт, который может быть изменён только вами! -- Вы можете найти и изменить контент вашего сайта в каталоге **data/[адрес_вашего_сайта]** -- После изменений откройте ваш сайт, переключите влево кнопку "0" в правом верхнем углу, затем нажмите кнопки **sign** и **publish** внизу -Следующие шаги: [Документация разработчика ZeroNet](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/site_development/getting_started/) +## Как я могу модифицировать Zeronet сайт? + +* Измените файлы расположенные в data/13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2 директории. + Когда закончите с изменением: + +```bash +$ zeronet.py siteSign 13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2 +- Signing site (Подпись сайта): 13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2... +Private key (Приватный ключ) (input hidden): +``` + +* Введите секретный ключ, который вы получили при создании сайта, потом: + +```bash +$ zeronet.py sitePublish 13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2 +... +Site:13DNDk..bhC2 Publishing to 3/10 peers... +Site:13DNDk..bhC2 Successfuly published to 3 peers +- Serving files.... +``` + +* Вот и всё! Вы успешно подписали и опубликовали свои изменения. + ## Поддержите проект - -- Bitcoin: 1ZeroNetyV5mKY9JF1gsm82TuBXHpfdLX (Рекомендуем) +- Bitcoin: 1ZeroNetyV5mKY9JF1gsm82TuBXHpfdLX (Preferred) - LiberaPay: https://liberapay.com/PramUkesh - Paypal: https://paypal.me/PramUkesh -- Другие способы: [Donate](!https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/help_zeronet/donate/#help-to-keep-zeronet-development-alive) +- Others: [Donate](!https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/help_zeronet/donate/#help-to-keep-zeronet-development-alive) + #### Спасибо! -- Здесь вы можете получить больше информации, помощь, прочитать список изменений и исследовать ZeroNet сайты: https://www.reddit.com/r/zeronetx/ -- Общение происходит на канале [#zeronet @ FreeNode](https://kiwiirc.com/client/irc.freenode.net/zeronet) или в [Gitter](https://gitter.im/canewsin/ZeroNet) -- Электронная почта: canews.in@gmail.com +* Больше информации, помощь, журнал изменений, zeronet сайты: https://www.reddit.com/r/zeronetx/ +* Приходите, пообщайтесь с нами: [#zeronet @ FreeNode](https://kiwiirc.com/client/irc.freenode.net/zeronet) или на [gitter](https://gitter.im/canewsin/ZeroNet) +* Email: canews.in@gmail.com diff --git a/README.md b/README.md index 70b79adc..e45d5cad 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # ZeroNet [![tests](https://github.com/ZeroNetX/ZeroNet/actions/workflows/tests.yml/badge.svg)](https://github.com/ZeroNetX/ZeroNet/actions/workflows/tests.yml) [![Documentation](https://img.shields.io/badge/docs-faq-brightgreen.svg)](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/faq/) [![Help](https://img.shields.io/badge/keep_this_project_alive-donate-yellow.svg)](https://docs.zeronet.dev/1DeveLopDZL1cHfKi8UXHh2UBEhzH6HhMp/help_zeronet/donate/) [![Docker Pulls](https://img.shields.io/docker/pulls/canewsin/zeronet)](https://hub.docker.com/r/canewsin/zeronet) + Decentralized websites using Bitcoin crypto and the BitTorrent network - https://zeronet.dev / [ZeroNet Site](http://127.0.0.1:43110/1ZeroNetyV5mKY9JF1gsm82TuBXHpfdLX/), Unlike Bitcoin, ZeroNet Doesn't need a blockchain to run, But uses cryptography used by BTC, to ensure data integrity and validation. @@ -99,24 +100,6 @@ Decentralized websites using Bitcoin crypto and the BitTorrent network - https:/ #### Docker There is an official image, built from source at: https://hub.docker.com/r/canewsin/zeronet/ -### Online Proxies -Proxies are like seed boxes for sites(i.e ZNX runs on a cloud vps), you can try zeronet experience from proxies. Add your proxy below if you have one. - -#### Official ZNX Proxy : - -https://proxy.zeronet.dev/ - -https://zeronet.dev/ - -#### From Community - -https://0net-preview.com/ - -https://portal.ngnoid.tv/ - -https://zeronet.ipfsscan.io/ - - ### Install from source - `wget https://github.com/ZeroNetX/ZeroNet/releases/latest/download/ZeroNet-src.zip` diff --git a/plugins b/plugins index 689d9309..d3cbe172 160000 --- a/plugins +++ b/plugins @@ -1 +1 @@ -Subproject commit 689d9309f73371f4681191b125ec3f2e14075eeb +Subproject commit d3cbe172712951f43bb6589e92e9e9eeb86c3172 diff --git a/requirements.txt b/requirements.txt index 538a6dfc..b3df57ea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ greenlet==0.4.16; python_version <= "3.6" gevent>=20.9.0; python_version >= "3.7" msgpack>=0.4.4 base58 -merkletools @ git+https://github.com/ZeroNetX/pymerkletools.git@dev +merkletools rsa PySocks>=1.6.8 pyasn1 diff --git a/src/Config.py b/src/Config.py index a9208d55..b067e13f 100644 --- a/src/Config.py +++ b/src/Config.py @@ -13,8 +13,8 @@ import time class Config(object): def __init__(self, argv): - self.version = "0.9.0" - self.rev = 4630 + self.version = "0.7.6" + self.rev = 4565 self.argv = argv self.action = None self.test_parser = None @@ -82,12 +82,34 @@ class Config(object): from Crypt import CryptHash access_key_default = CryptHash.random(24, "base64") # Used to allow restrited plugins when multiuser plugin is enabled trackers = [ + "zero://boot3rdez4rzn36x.onion:15441", "http://open.acgnxtracker.com:80/announce", # DE "http://tracker.bt4g.com:2095/announce", # Cloudflare - "http://tracker.files.fm:6969/announce", - "http://t.publictracker.xyz:6969/announce", + "zero://2602:ffc5::c5b2:5360:26312", # US/ATL + "zero://145.239.95.38:15441", + "zero://188.116.183.41:26552", + "zero://145.239.95.38:15441", + "zero://211.125.90.79:22234", + "zero://216.189.144.82:26312", + "zero://45.77.23.92:15555", + "zero://51.15.54.182:21041", "https://tracker.lilithraws.cf:443/announce", - "https://tracker.babico.name.tr:443/announce", + "udp://code2chicken.nl:6969/announce", + "udp://abufinzio.monocul.us:6969/announce", + "udp://tracker.0x.tf:6969/announce", + "udp://tracker.zerobytes.xyz:1337/announce", + "udp://vibe.sleepyinternetfun.xyz:1738/announce", + "udp://www.torrent.eu.org:451/announce", + "zero://k5w77dozo3hy5zualyhni6vrh73iwfkaofa64abbilwyhhd3wgenbjqd.onion:15441", + "zero://2kcb2fqesyaevc4lntogupa4mkdssth2ypfwczd2ov5a3zo6ytwwbayd.onion:15441", + "zero://gugt43coc5tkyrhrc3esf6t6aeycvcqzw7qafxrjpqbwt4ssz5czgzyd.onion:15441", + "zero://hb6ozikfiaafeuqvgseiik4r46szbpjfu66l67wjinnyv6dtopuwhtqd.onion:15445", + "zero://75pmmcbp4vvo2zndmjnrkandvbg6jyptygvvpwsf2zguj7urq7t4jzyd.onion:7777", + "zero://dw4f4sckg2ultdj5qu7vtkf3jsfxsah3mz6pivwfd6nv3quji3vfvhyd.onion:6969", + "zero://5vczpwawviukvd7grfhsfxp7a6huz77hlis4fstjkym5kmf4pu7i7myd.onion:15441", + "zero://ow7in4ftwsix5klcbdfqvfqjvimqshbm2o75rhtpdnsderrcbx74wbad.onion:15441", + "zero://agufghdtniyfwty3wk55drxxwj2zxgzzo7dbrtje73gmvcpxy4ngs4ad.onion:15441", + "zero://qn65si4gtcwdiliq7vzrwu62qrweoxb6tx2cchwslaervj6szuje66qd.onion:26117", ] # Platform specific if sys.platform.startswith("win"): @@ -251,7 +273,7 @@ class Config(object): self.parser.add_argument('--access_key', help='Plugin access key default: Random key generated at startup', default=access_key_default, metavar='key') self.parser.add_argument('--dist_type', help='Type of installed distribution', default='source') - self.parser.add_argument('--size_limit', help='Default site size limit in MB', default=25, type=int, metavar='limit') + self.parser.add_argument('--size_limit', help='Default site size limit in MB', default=10, type=int, metavar='limit') self.parser.add_argument('--file_size_limit', help='Maximum per file size limit in MB', default=10, type=int, metavar='limit') self.parser.add_argument('--connected_limit', help='Max connected peer per site', default=8, type=int, metavar='connected_limit') self.parser.add_argument('--global_connected_limit', help='Max connections', default=512, type=int, metavar='global_connected_limit') @@ -319,7 +341,8 @@ class Config(object): def loadTrackersFile(self): if not self.trackers_file: - self.trackers_file = ["trackers.txt", "{data_dir}/1HELLoE3sFD9569CLCbHEAVqvqV7U2Ri9d/trackers.txt"] + return None + self.trackers = self.arguments.trackers[:] for trackers_file in self.trackers_file: @@ -331,9 +354,6 @@ class Config(object): else: # Relative to zeronet.py trackers_file_path = self.start_dir + "/" + trackers_file - if not os.path.exists(trackers_file_path): - continue - for line in open(trackers_file_path): tracker = line.strip() if "://" in tracker and tracker not in self.trackers: diff --git a/src/Connection/ConnectionServer.py b/src/Connection/ConnectionServer.py index c9048398..090d96a6 100644 --- a/src/Connection/ConnectionServer.py +++ b/src/Connection/ConnectionServer.py @@ -32,7 +32,6 @@ class ConnectionServer(object): self.port = port self.last_connection_id = 0 # Connection id incrementer self.last_connection_id_current_version = 0 # Connection id incrementer for current client version - self.last_connection_id_supported_version = 0 # Connection id incrementer for last supported version self.log = logging.getLogger("ConnServer") self.port_opened = {} self.peer_blacklist = SiteManager.peer_blacklist @@ -158,10 +157,8 @@ class ConnectionServer(object): connection = Connection(self, ip, port, sock) self.connections.append(connection) rev = connection.handshake.get("rev", 0) - if rev >= 4560: - self.last_connection_id_supported_version += 1 - if rev == config.rev: - self.last_connection_id_current_version += 1 + if rev > 0 and rev == config.rev: + self.last_connection_id_current_version += 1 if ip not in config.ip_local: self.ips[ip] = connection connection.handleIncomingConnection(sock) @@ -228,10 +225,8 @@ class ConnectionServer(object): raise Exception("Connection event return error") else: rev = connection.handshake.get("rev", 0) - if rev >= 4560: - self.last_connection_id_supported_version += 1 - if rev == config.rev: - self.last_connection_id_current_version += 1 + if rev > 0 and rev == config.rev: + self.last_connection_id_current_version += 1 except Exception as err: connection.close("%s Connect error: %s" % (ip, Debug.formatException(err))) diff --git a/src/Content/ContentManager.py b/src/Content/ContentManager.py index 623cc707..27da402b 100644 --- a/src/Content/ContentManager.py +++ b/src/Content/ContentManager.py @@ -727,6 +727,7 @@ class ContentManager(object): elif "files_optional" in new_content: del new_content["files_optional"] + new_content["modified"] = int(time.time()) # Add timestamp if inner_path == "content.json": new_content["zeronet_version"] = config.version new_content["signs_required"] = content.get("signs_required", 1) @@ -746,11 +747,9 @@ class ContentManager(object): ) self.log.info("Correct %s in valid signers: %s" % (privatekey_address, valid_signers)) - signs_required = 1 if inner_path == "content.json" and privatekey_address == self.site.address: # If signing using the root key, then sign the valid signers - signs_required = new_content["signs_required"] - signers_data = "%s:%s" % (signs_required, ",".join(valid_signers)) + signers_data = "%s:%s" % (new_content["signs_required"], ",".join(valid_signers)) new_content["signers_sign"] = CryptBitcoin.sign(str(signers_data), privatekey) if not new_content["signers_sign"]: self.log.info("Old style address, signers_sign is none") @@ -758,32 +757,15 @@ class ContentManager(object): self.log.info("Signing %s..." % inner_path) if "signs" in new_content: - # del(new_content["signs"]) # Delete old signs - old_signs_content = new_content["signs"] - del(new_content["signs"]) - else: - old_signs_content = None + del(new_content["signs"]) # Delete old signs if "sign" in new_content: del(new_content["sign"]) # Delete old sign (backward compatibility) - if signs_required > 1: - has_valid_sign = False - sign_content = json.dumps(new_content, sort_keys=True) - for signer in valid_signers: - res = CryptBitcoin.verify(sign_content,signer,old_signs_content[signer]); - print(res) - if res: - has_valid_sign = has_valid_sign or res - if has_valid_sign: - new_content["modified"] = content["modified"] - sign_content = json.dumps(new_content, sort_keys=True) - else: - new_content["modified"] = int(time.time()) # Add timestamp - sign_content = json.dumps(new_content, sort_keys=True) + sign_content = json.dumps(new_content, sort_keys=True) sign = CryptBitcoin.sign(sign_content, privatekey) # new_content["signs"] = content.get("signs", {}) # TODO: Multisig if sign: # If signing is successful (not an old address) - new_content["signs"] = old_signs_content or {} + new_content["signs"] = {} new_content["signs"][privatekey_address] = sign self.verifyContent(inner_path, new_content) @@ -818,9 +800,7 @@ class ContentManager(object): # Return: The required number of valid signs for the content.json def getSignsRequired(self, inner_path, content=None): - if not content: - return 1 - return content.get("signs_required", 1) + return 1 # Todo: Multisig def verifyCertSign(self, user_address, user_auth_type, user_name, issuer_address, sign): from Crypt import CryptBitcoin @@ -1008,16 +988,14 @@ class ContentManager(object): if inner_path != "content.json" and not self.verifyCert(inner_path, new_content): # Check if cert valid raise VerifyError("Invalid cert!") - valid_signs = [] + valid_signs = 0 for address in valid_signers: if address in signs: - result = CryptBitcoin.verify(sign_content, address, signs[address]) - if result: - valid_signs.append(address) - if len(valid_signs) >= signs_required: + valid_signs += CryptBitcoin.verify(sign_content, address, signs[address]) + if valid_signs >= signs_required: break # Break if we has enough signs - if len(valid_signs) < signs_required: - raise VerifyError("Valid signs: %s/%s, Valid Signers : %s" % (len(valid_signs), signs_required, valid_signs)) + if valid_signs < signs_required: + raise VerifyError("Valid signs: %s/%s" % (valid_signs, signs_required)) else: return self.verifyContent(inner_path, new_content) else: # Old style signing diff --git a/src/Crypt/CryptConnection.py b/src/Crypt/CryptConnection.py index c0903e84..ebbc6295 100644 --- a/src/Crypt/CryptConnection.py +++ b/src/Crypt/CryptConnection.py @@ -127,10 +127,6 @@ class CryptConnectionManager: "/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA" ] self.openssl_env['CN'] = random.choice(self.fakedomains) - environ = os.environ - environ['OPENSSL_CONF'] = self.openssl_env['OPENSSL_CONF'] - environ['RANDFILE'] = self.openssl_env['RANDFILE'] - environ['CN'] = self.openssl_env['CN'] if os.path.isfile(self.cert_pem) and os.path.isfile(self.key_pem): self.createSslContexts() @@ -156,7 +152,7 @@ class CryptConnectionManager: self.log.debug("Running: %s" % cmd) proc = subprocess.Popen( cmd, shell=True, stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, env=environ + stdout=subprocess.PIPE, env=self.openssl_env ) back = proc.stdout.read().strip().decode(errors="replace").replace("\r", "") proc.wait() @@ -179,7 +175,7 @@ class CryptConnectionManager: self.log.debug("Generating certificate key and signing request...") proc = subprocess.Popen( cmd, shell=True, stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, env=environ + stdout=subprocess.PIPE, env=self.openssl_env ) back = proc.stdout.read().strip().decode(errors="replace").replace("\r", "") proc.wait() @@ -198,7 +194,7 @@ class CryptConnectionManager: self.log.debug("Generating RSA cert...") proc = subprocess.Popen( cmd, shell=True, stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, env=environ + stdout=subprocess.PIPE, env=self.openssl_env ) back = proc.stdout.read().strip().decode(errors="replace").replace("\r", "") proc.wait() diff --git a/src/File/FileRequest.py b/src/File/FileRequest.py index c082c378..85bbcdce 100644 --- a/src/File/FileRequest.py +++ b/src/File/FileRequest.py @@ -109,35 +109,31 @@ class FileRequest(object): return False inner_path = params.get("inner_path", "") + current_content_modified = site.content_manager.contents.get(inner_path, {}).get("modified", 0) + body = params["body"] + if not inner_path.endswith("content.json"): self.response({"error": "Only content.json update allowed"}) self.connection.badAction(5) return - current_content_modified = site.content_manager.contents.get(inner_path, {}).get("modified", 0) should_validate_content = True if "modified" in params and params["modified"] <= current_content_modified: should_validate_content = False valid = None # Same or earlier content as we have - - body = params["body"] - if not body: # No body sent, we have to download it first + elif not body: # No body sent, we have to download it first site.log.debug("Missing body from update for file %s, downloading ..." % inner_path) peer = site.addPeer(self.connection.ip, self.connection.port, return_peer=True, source="update") # Add or get peer try: body = peer.getFile(site.address, inner_path).read() except Exception as err: site.log.debug("Can't download updated file %s: %s" % (inner_path, err)) - self.response({"error": "Invalid File update: Failed to download updated file content"}) + self.response({"error": "File invalid update: Can't download updaed file"}) self.connection.badAction(5) return if should_validate_content: try: - if type(body) is str: - body = body.encode() - # elif type(body) is list: - # content = json.loads(bytes(list).decode()) content = json.loads(body.decode()) except Exception as err: site.log.debug("Update for %s is invalid JSON: %s" % (inner_path, err)) @@ -165,19 +161,21 @@ class FileRequest(object): site.onFileDone(inner_path) # Trigger filedone - # Download every changed file from peer - peer = site.addPeer(self.connection.ip, self.connection.port, return_peer=True, source="update") # Add or get peer - # On complete publish to other peers - diffs = params.get("diffs", {}) - site.onComplete.once(lambda: site.publish(inner_path=inner_path, diffs=diffs, limit=6), "publish_%s" % inner_path) + if inner_path.endswith("content.json"): # Download every changed file from peer + peer = site.addPeer(self.connection.ip, self.connection.port, return_peer=True, source="update") # Add or get peer + # On complete publish to other peers + diffs = params.get("diffs", {}) + site.onComplete.once(lambda: site.publish(inner_path=inner_path, diffs=diffs, limit=6), "publish_%s" % inner_path) - # Load new content file and download changed files in new thread - def downloader(): - site.downloadContent(inner_path, peer=peer, diffs=params.get("diffs", {})) + # Load new content file and download changed files in new thread + def downloader(): + site.downloadContent(inner_path, peer=peer, diffs=params.get("diffs", {})) + del self.server.files_parsing[file_uri] + + gevent.spawn(downloader) + else: del self.server.files_parsing[file_uri] - gevent.spawn(downloader) - self.response({"ok": "Thanks, file %s updated!" % inner_path}) self.connection.goodAction() diff --git a/src/File/FileServer.py b/src/File/FileServer.py index b7a942fc..7f73017e 100644 --- a/src/File/FileServer.py +++ b/src/File/FileServer.py @@ -72,12 +72,6 @@ class FileServer(ConnectionServer): self.ui_server = None def getRandomPort(self, ip, port_range_from, port_range_to): - """Generates Random Port from given range - Args: - ip: IP Address - port_range_from: From Range - port_range_to: to Range - """ self.log.info("Getting random port in range %s-%s..." % (port_range_from, port_range_to)) tried = [] for bind_retry in range(100): diff --git a/src/Plugin/PluginManager.py b/src/Plugin/PluginManager.py index 56540e60..dbafa98f 100644 --- a/src/Plugin/PluginManager.py +++ b/src/Plugin/PluginManager.py @@ -16,9 +16,7 @@ import plugins class PluginManager: def __init__(self): self.log = logging.getLogger("PluginManager") - self.path_plugins = None - if plugins.__file__: - self.path_plugins = os.path.dirname(os.path.abspath(plugins.__file__)); + self.path_plugins = os.path.abspath(os.path.dirname(plugins.__file__)) self.path_installed_plugins = config.data_dir + "/__plugins__" self.plugins = defaultdict(list) # Registered plugins (key: class name, value: list of plugins for class) self.subclass_order = {} # Record the load order of the plugins, to keep it after reload @@ -34,8 +32,7 @@ class PluginManager: self.config.setdefault("builtin", {}) - if self.path_plugins: - sys.path.append(os.path.join(os.getcwd(), self.path_plugins)) + sys.path.append(os.path.join(os.getcwd(), self.path_plugins)) self.migratePlugins() if config.debug: # Auto reload Plugins on file change @@ -130,8 +127,6 @@ class PluginManager: def loadPlugins(self): all_loaded = True s = time.time() - if self.path_plugins is None: - return for plugin in self.listPlugins(): self.log.debug("Loading plugin: %s (%s)" % (plugin["name"], plugin["source"])) if plugin["source"] != "builtin": diff --git a/src/Site/Site.py b/src/Site/Site.py index d6179307..354fe9c0 100644 --- a/src/Site/Site.py +++ b/src/Site/Site.py @@ -143,7 +143,7 @@ class Site(object): # Next size limit based on current size def getNextSizeLimit(self): - size_limits = [25, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000] + size_limits = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000] size = self.settings.get("size", 0) for size_limit in size_limits: if size * 1.2 < size_limit * 1024 * 1024: diff --git a/src/Site/SiteStorage.py b/src/Site/SiteStorage.py index 27032e79..c12a80b0 100644 --- a/src/Site/SiteStorage.py +++ b/src/Site/SiteStorage.py @@ -260,7 +260,7 @@ class SiteStorage(object): # Open file object @thread_pool_fs_read.wrap def read(self, inner_path, mode="rb"): - return self.open(inner_path, mode).read() + return open(self.getPath(inner_path), mode).read() @thread_pool_fs_write.wrap def writeThread(self, inner_path, content): @@ -369,12 +369,8 @@ class SiteStorage(object): # Load and parse json file @thread_pool_fs_read.wrap def loadJson(self, inner_path): - try: - with self.open(inner_path, "r", encoding="utf8") as file: - return json.load(file) - except Exception as err: - self.log.warning("Json load error: %s" % Debug.formatException(err)) - return None + with self.open(inner_path, "r", encoding="utf8") as file: + return json.load(file) # Write formatted json file def writeJson(self, inner_path, data): @@ -463,8 +459,7 @@ class SiteStorage(object): else: try: ok = self.site.content_manager.verifyFile(file_inner_path, open(file_path, "rb")) - except Exception as _err: - err = _err + except Exception as err: ok = False if not ok: diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py index 4a4e0545..dbd3ca67 100644 --- a/src/Ui/UiRequest.py +++ b/src/Ui/UiRequest.py @@ -543,37 +543,18 @@ class UiRequest(object): if show_loadingscreen: meta_tags += ''; - - def xescape(s): - '''combines parts from re.escape & html.escape''' - # https://github.com/python/cpython/blob/3.10/Lib/re.py#L267 - # '&' is handled otherwise - re_chars = {i: '\\' + chr(i) for i in b'()[]{}*+-|^$\\.~# \t\n\r\v\f'} - # https://github.com/python/cpython/blob/3.10/Lib/html/__init__.py#L12 - html_chars = { - '<' : '<', - '>' : '>', - '"' : '"', - "'" : ''', - } - # we can't replace '&' because it makes certain zites work incorrectly - # it should however in no way interfere with re.sub in render - repl = {} - repl.update(re_chars) - repl.update(html_chars) - return s.translate(repl) - + return self.render( "src/Ui/template/wrapper.html", server_url=server_url, inner_path=inner_path, - file_url=xescape(file_url), - file_inner_path=xescape(file_inner_path), + file_url=re.escape(file_url), + file_inner_path=re.escape(file_inner_path), address=site.address, - title=xescape(title), + title=html.escape(title), body_style=body_style, meta_tags=meta_tags, - query_string=xescape(inner_query_string), + query_string=re.escape(inner_query_string), wrapper_key=site.settings["wrapper_key"], ajax_key=site.settings["ajax_key"], wrapper_nonce=wrapper_nonce, @@ -749,10 +730,7 @@ class UiRequest(object): def replaceHtmlVariables(self, block, path_parts): user = self.getCurrentUser() - if user and user.settings: - themeclass = "theme-%-6s" % re.sub("[^a-z]", "", user.settings.get("theme", "light")) - else: - themeclass = "theme-light" + themeclass = "theme-%-6s" % re.sub("[^a-z]", "", user.settings.get("theme", "light")) block = block.replace(b"{themeclass}", themeclass.encode("utf8")) if path_parts: diff --git a/src/Ui/UiWebsocket.py b/src/Ui/UiWebsocket.py index 2f982e1d..9865a1f1 100644 --- a/src/Ui/UiWebsocket.py +++ b/src/Ui/UiWebsocket.py @@ -327,10 +327,7 @@ class UiWebsocket(object): def actionAs(self, to, address, cmd, params=[]): if not self.hasSitePermission(address, cmd=cmd): - #TODO! Return this as error ? return self.response(to, "No permission for site %s" % address) - if not self.server.sites.get(address): - return self.response(to, {"error": "Site Does Not Exist: %s" % address}) req_self = copy.copy(self) req_self.site = self.server.sites.get(address) req_self.hasCmdPermission = self.hasCmdPermission # Use the same permissions as current site @@ -422,15 +419,10 @@ class UiWebsocket(object): is_user_content = file_info and ("cert_signers" in file_info or "cert_signers_pattern" in file_info) if is_user_content and privatekey is None: cert = self.user.getCert(self.site.address) - if not cert: - error = "Site sign failed: No certificate selected for Site: %s, Hence Signing inner_path: %s Failed, Try Adding/Selecting User Cert via Site Login" % (self.site.address, inner_path) - self.log.error(error) - return self.response(to, {"error": error}) - else: - extend["cert_auth_type"] = cert["auth_type"] - extend["cert_user_id"] = self.user.getCertUserId(site.address) - extend["cert_sign"] = cert["cert_sign"] - self.log.debug("Extending content.json with cert %s" % extend["cert_user_id"]) + extend["cert_auth_type"] = cert["auth_type"] + extend["cert_user_id"] = self.user.getCertUserId(site.address) + extend["cert_sign"] = cert["cert_sign"] + self.log.debug("Extending content.json with cert %s" % extend["cert_user_id"]) if not self.hasFilePermission(inner_path): self.log.error("SiteSign error: you don't own this site & site owner doesn't allow you to do so.") diff --git a/src/main.py b/src/main.py index ec90f4d9..6ba85052 100644 --- a/src/main.py +++ b/src/main.py @@ -254,9 +254,8 @@ class Actions(object): file_correct = site.content_manager.verifyFile( content_inner_path, site.storage.open(content_inner_path, "rb"), ignore_same=False ) - except Exception as exp: + except Exception as err: file_correct = False - err = exp if file_correct is True: logging.info("[OK] %s (Done in %.3fs)" % (content_inner_path, time.time() - s)) diff --git a/src/util/Diff.py b/src/util/Diff.py index 53b82c5a..8281188b 100644 --- a/src/util/Diff.py +++ b/src/util/Diff.py @@ -42,8 +42,6 @@ def patch(old_f, actions): continue elif action == "+": # Add lines for add_line in param: - if type(add_line) is str: - add_line = add_line.encode() new_f.write(add_line) else: raise "Unknown action: %s" % action diff --git a/trackers.txt b/trackers.txt deleted file mode 100644 index a42f8ca4..00000000 --- a/trackers.txt +++ /dev/null @@ -1,142 +0,0 @@ -udp://tracker.opentrackr.org:1337/announce -udp://explodie.org:6969/announce -udp://open.stealth.si:80/announce -http://tracker.ipv6tracker.ru:80/announce -udp://tracker.birkenwald.de:6969/announce -udp://tracker.moeking.me:6969/announce -http://tracker.bt4g.com:2095/announce -https://tracker.nanoha.org:443/announce -http://tracker.files.fm:6969/announce -http://open.acgnxtracker.com:80/announce -udp://tracker.army:6969/announce -udp://fe.dealclub.de:6969/announce -udp://tracker.leech.ie:1337/announce -udp://tracker.altrosky.nl:6969/announce -https://tracker.cyber-hub.net:443/announce -https://tracker.lilithraws.cf:443/announce -http://bt.okmp3.ru:2710/announce -udp://vibe.sleepyinternetfun.xyz:1738/announce -udp://open.publictracker.xyz:6969/announce -udp://tracker.bitsearch.to:1337/announce -udp://tracker.pomf.se:80/announce -https://tr.burnabyhighstar.com:443/announce -https://tr.abiir.top:443/announce -udp://open.free-tracker.ga:6969/announce -http://i-p-v-6.tk:6969/announce -http://open-v6.demonoid.ch:6969/announce -udp://aarsen.me:6969/announce -udp://htz3.noho.st:6969/announce -udp://uploads.gamecoast.net:6969/announce -udp://mail.zasaonsk.ga:6969/announce -udp://tracker.joybomb.tw:6969/announce -udp://tracker.jonaslsa.com:6969/announce -udp://leefafa.tk:6969/announce -udp://carr.codes:6969/announce -https://tr.fuckbitcoin.xyz:443/announce -udp://tracker.cubonegro.xyz:6969/announce -udp://tracker.skynetcloud.site:6969/announce -http://tracker4.itzmx.com:2710/announce -https://tracker.lilithraws.org:443/announce -udp://tracker.novaopcj.eu.org:6969/announce -udp://exodus.desync.com:6969/announce -http://t.acg.rip:6699/announce -udp://tracker2.dler.com:80/announce -udp://6ahddutb1ucc3cp.ru:6969/announce -udp://tracker.blacksparrowmedia.net:6969/announce -http://fxtt.ru:80/announce -udp://tracker.auctor.tv:6969/announce -udp://torrentclub.space:6969/announce -udp://zecircle.xyz:6969/announce -udp://psyco.fr:6969/announce -udp://fh2.cmp-gaming.com:6969/announce -udp://new-line.net:6969/announce -udp://torrents.artixlinux.org:6969/announce -udp://bt.ktrackers.com:6666/announce -udp://static.54.161.216.95.clients.your-server.de:6969/announce -udp://cpe-104-34-3-152.socal.res.rr.com:6969/announce -http://t.overflow.biz:6969/announce -udp://tracker1.myporn.club:9337/announce -udp://moonburrow.club:6969/announce -udp://tracker.artixlinux.org:6969/announce -https://t1.hloli.org:443/announce -udp://bt1.archive.org:6969/announce -udp://tracker.theoks.net:6969/announce -udp://tracker.4.babico.name.tr:3131/announce -udp://buddyfly.top:6969/announce -udp://ipv6.tracker.harry.lu:80/announce -udp://public.publictracker.xyz:6969/announce -udp://mail.artixlinux.org:6969/announce -udp://v1046920.hosted-by-vdsina.ru:6969/announce -udp://tracker.cyberia.is:6969/announce -udp://tracker.beeimg.com:6969/announce -udp://creative.7o7.cx:6969/announce -udp://open.dstud.io:6969/announce -udp://laze.cc:6969/announce -udp://download.nerocloud.me:6969/announce -udp://cutscloud.duckdns.org:6969/announce -https://tracker.jiesen.life:8443/announce -udp://jutone.com:6969/announce -udp://wepzone.net:6969/announce -udp://ipv4.tracker.harry.lu:80/announce -udp://tracker.tcp.exchange:6969/announce -udp://f1sh.de:6969/announce -udp://movies.zsw.ca:6969/announce -https://tracker1.ctix.cn:443/announce -udp://sanincode.com:6969/announce -udp://www.torrent.eu.org:451/announce -udp://open.4ever.tk:6969/announce -https://tracker2.ctix.cn:443/announce -udp://bt2.archive.org:6969/announce -http://t.nyaatracker.com:80/announce -udp://yahor.ftp.sh:6969/announce -udp://tracker.openbtba.com:6969/announce -udp://tracker.dler.com:6969/announce -udp://tracker-udp.gbitt.info:80/announce -udp://tracker.srv00.com:6969/announce -udp://tracker.pimpmyworld.to:6969/announce -http://tracker.gbitt.info:80/announce -udp://tracker6.lelux.fi:6969/announce -http://tracker.vrpnet.org:6969/announce -http://00.xxtor.com:443/announce -http://vps02.net.orel.ru:80/announce -udp://tracker.yangxiaoguozi.cn:6969/announce -udp://rep-art.ynh.fr:6969/announce -https://tracker.imgoingto.icu:443/announce -udp://mirror.aptus.co.tz:6969/announce -udp://tracker.lelux.fi:6969/announce -udp://tracker.torrent.eu.org:451/announce -udp://admin.52ywp.com:6969/announce -udp://thouvenin.cloud:6969/announce -http://vps-dd0a0715.vps.ovh.net:6969/announce -udp://bubu.mapfactor.com:6969/announce -udp://94-227-232-84.access.telenet.be:6969/announce -udp://epider.me:6969/announce -udp://camera.lei001.com:6969/announce -udp://tamas3.ynh.fr:6969/announce -https://tracker.tamersunion.org:443/announce -udp://ftp.pet:2710/announce -udp://p4p.arenabg.com:1337/announce -http://tracker.mywaifu.best:6969/announce -udp://tracker.monitorit4.me:6969/announce -udp://ipv6.tracker.monitorit4.me:6969/announce -zero://k5w77dozo3hy5zualyhni6vrh73iwfkaofa64abbilwyhhd3wgenbjqd.onion:15441 -zero://2kcb2fqesyaevc4lntogupa4mkdssth2ypfwczd2ov5a3zo6ytwwbayd.onion:15441 -zero://5vczpwawviukvd7grfhsfxp7a6huz77hlis4fstjkym5kmf4pu7i7myd.onion:15441 -zero://pn4q2zzt2pw4nk7yidxvsxmydko7dfibuzxdswi6gu6ninjpofvqs2id.onion:15441 -zero://6i54dd5th73oelv636ivix6sjnwfgk2qsltnyvswagwphub375t3xcad.onion:15441 -zero://tl74auz4tyqv4bieeclmyoe4uwtoc2dj7fdqv4nc4gl5j2bwg2r26bqd.onion:15441 -zero://wlxav3szbrdhest4j7dib2vgbrd7uj7u7rnuzg22cxbih7yxyg2hsmid.onion:15441 -zero://zy7wttvjtsijt5uwmlar4yguvjc2gppzbdj4v6bujng6xwjmkdg7uvqd.onion:15441 -zero://rlcjomszyitxpwv7kzopmqgzk3bdpsxeull4c3s6goszkk6h2sotfoad.onion:15441 -zero://gugt43coc5tkyrhrc3esf6t6aeycvcqzw7qafxrjpqbwt4ssz5czgzyd.onion:15441 -zero://ow7in4ftwsix5klcbdfqvfqjvimqshbm2o75rhtpdnsderrcbx74wbad.onion:15441 -zero://57hzgtu62yzxqgbvgxs7g3lfck3za4zrda7qkskar3tlak5recxcebyd.onion:15445 -zero://hb6ozikfiaafeuqvgseiik4r46szbpjfu66l67wjinnyv6dtopuwhtqd.onion:15445 -zero://qn65si4gtcwdiliq7vzrwu62qrweoxb6tx2cchwslaervj6szuje66qd.onion:26117 -zero://s3j2s5pjdfesbsmaqx6alsumaxxdxibmhv4eukmqpv3vqj6f627qx5yd.onion:15441 -zero://agufghdtniyfwty3wk55drxxwj2zxgzzo7dbrtje73gmvcpxy4ngs4ad.onion:15441 -zero://kgsvasoakvj4gnjiy7zemu34l3hq46dn5eauqkn76jpowmilci5t2vqd.onion:15445 -zero://dslesoe72bdfwfu4cfqa2wpd4hr3fhlu4zv6mfsjju5xlpmssouv36qd.onion:15441 -zero://f2hnjbggc3c2u2apvxdugirnk6bral54ibdoul3hhvu7pd4fso5fq3yd.onion:15441 -zero://skdeywpgm5xncpxbbr4cuiip6ey4dkambpanog6nruvmef4f3e7o47qd.onion:15441 -zero://tqmo2nffqo4qc5jgmz3me5eri3zpgf3v2zciufzmhnvznjve5c3argad.onion:15441 \ No newline at end of file diff --git a/zeronet.py b/zeronet.py index 457efb19..dacd2096 100755 --- a/zeronet.py +++ b/zeronet.py @@ -66,7 +66,7 @@ def displayErrorMessage(err, error_log_path): res = ctypes.windll.user32.MessageBoxW(0, err_title, "ZeroNet error", MB_YESNOCANCEL | MB_ICONEXCLAIMATION) if res == ID_YES: import webbrowser - report_url = "https://github.com/ZeroNetX/ZeroNet/issues/new?assignees=&labels=&template=bug-report.md&title=%s" + report_url = "https://github.com/HelloZeroNet/ZeroNet/issues/new?assignees=&labels=&template=bug-report.md&title=%s" webbrowser.open(report_url % urllib.parse.quote("Unhandled exception: %s" % err_message)) if res in [ID_YES, ID_NO]: subprocess.Popen(['notepad.exe', error_log_path])