Compare commits

..

72 Commits

Author SHA1 Message Date
Kevin F
61051d5711 Removed old scripts 2023-01-16 23:33:57 -06:00
Kevin F
59ad2731ba Disconnect peers who stem a bad block 2023-01-16 23:31:30 -06:00
Kevin F
560a20e90a Only expose wot to rpc if rpc is active 2023-01-16 23:30:50 -06:00
Kevin F
ce3a548c70 Added create block RPC wrapper 2023-01-16 23:29:50 -06:00
Kevin F
8712a1c401 Changed rpc block wrapper to use multiprocessing 2023-01-12 21:51:27 -06:00
Kevin F
8511fb42b6 Added test for multiprocess wrapper 2023-01-12 21:51:03 -06:00
Kevin F
9eb2e5d413 Added multiprocess wrapper to do simple function calls in a seperate process 2023-01-12 21:42:22 -06:00
Kevin F
39c01fdbc5 Improved RPC, added threaded RPC with result fetcher 2023-01-12 00:23:28 -06:00
Kevin F
7bcef03592 Added setunixsocket and settcpsocket helper commands to RPC plugin 2023-01-11 16:51:11 -06:00
Kevin F
2b224cae84 Added create_block RPC endpoint 2023-01-10 22:08:08 -06:00
Kevin F
7895442b51 Respond to OPTIONS in rpc 2023-01-04 00:52:15 -06:00
Kevin F
474ef21163 Remove old dispatcher for getting blocks in RPC blocks wrapper 2023-01-02 19:36:37 -06:00
Kevin F
8e35a79864 Started on trust identity CLI menu option 2022-12-09 19:46:29 +00:00
Kevin F
8e730cef98 WOT API can now serialize identities 2022-12-02 21:42:11 +00:00
Kevin F
738fa0c361 Ping the RPC api before using the wot CLI 2022-12-02 21:41:48 +00:00
Kevin F
b3eb0caffd Add result plugin to reduce confusing use of exceptions 2022-12-02 21:41:10 +00:00
Kevin F
446662cc60 Fix RPC plugin server binding incorrectly to TCP and doubling up JSON encoding 2022-12-02 21:40:33 +00:00
Kevin F
180116a55d Fix killdaemon logging 2022-12-02 21:19:42 +00:00
Kevin F
bc3d6571bb merge seattle work 2022-11-27 01:03:44 +00:00
Kevin F
30d50ceacf merge seattle work 2022-11-27 01:03:36 +00:00
Kevin F
e84ad93de7 work on wot cli 2022-11-22 00:57:14 -05:00
Kevin F
84e16e5b82 bump dependencies 2022-10-31 17:01:15 +00:00
Kevin F
cd3a7cd7b2 Added identity generation 2022-10-22 06:22:29 +00:00
Kevin F
24e0157e15 Updated dockerfile 2022-10-22 06:22:05 +00:00
Kevin F
c2db671a85 Work on secure identity keystorage using system keyring 2022-10-17 20:45:45 +00:00
Kevin F
9501d73546 Adding WOT API to RPC to enable 3rd party apps like merkato 2022-10-14 18:26:07 +00:00
Kevin F
4572f255fb Wot adjustments, blockdb plugin events 2022-10-01 04:25:46 +00:00
Kevin F
20393a547e bump dependencies 2022-09-27 19:21:31 +00:00
Kevin F
015a072b0b Fix test writing to wrong test dir directory 2022-09-27 19:08:58 +00:00
Kevin F
5ae5897703 Removed defunct utils that will probably never be used again 2022-09-27 19:06:18 +00:00
Kevin F
e9efffff34 Removed crappy logger and replaced it with a sane built in logging logger 2022-09-27 17:21:00 +00:00
Kevin F
2eea681e98 Removed defunct tests and fixed remaining tests 2022-09-27 00:49:51 +00:00
Kevin F
3852b15c89 Fix gossip server not closing connections 2022-09-27 00:49:25 +00:00
Kevin F
3643e4f8d7 Removed lots of defunct cruft 2022-09-26 20:06:05 +00:00
Kevin F
8676a18c87 Split up requirements that default official plugins have 2022-09-26 20:04:03 +00:00
Kevin F
97d8662f15 started splitting dependencies by plugin 2022-09-25 23:18:18 -04:00
Kevin F
a517ad3aee Mostly finished with wot command processing 2022-09-23 17:31:34 -04:00
Kevin F
d915a2aaed handle unix peer socket file not existing 2022-09-17 01:24:11 -05:00
Kevin F
25e705c0b2 Removed sqlite as dependency 2022-09-17 01:23:27 -05:00
Kevin F
6f3e5aebd9 Removed defunct Onionrusers 2022-09-17 01:23:01 -05:00
Kevin F
584bc6b73f + Added ONIONR_PROFILING enviornment variable to profile onionr daemon or commands
+ Added SIGUSR1 handler to dump stacktrace of all active threads
2022-09-17 01:22:42 -05:00
Kevin F
171ea25f46 Wot import fixes 2022-09-17 00:02:49 -05:00
Kevin F
2c9836c54f Added REPL plugin 2022-09-16 23:33:39 -05:00
Kevin F
a036c1839f Added event for main loop 2022-09-16 23:24:44 -05:00
Kevin F
6ad36bf4e5 Removed deprecated DB code and onioncrypto 2022-09-16 23:24:25 -05:00
Kevin F
cdeaa403af Added set wrapper to contain identities
Finished signature revoking implementation
2022-09-15 20:03:29 -05:00
Kevin F
fae9521d8f Made trust distance test graph generation reliable 2022-09-15 20:01:59 -05:00
Kevin F
05e04ef557 Adjusted trust signatures to sign the wot command 2022-09-15 01:27:46 -05:00
Kevin F
5bb43326e7 Finished tests for trust payload processing 2022-09-14 12:35:20 -05:00
Kevin F
9058f7bee5 Added basic test for trust payload processing 2022-09-13 21:40:39 -05:00
Kevin F
08d8fda857 developing signature processing in wot 2022-09-13 12:29:50 -05:00
Kevin F
650e943182 Work on WOT block processing and signatures 2022-09-08 18:44:23 -05:00
Kevin F
e3d06ff0f5 Defunct code removal 2022-09-01 21:31:49 -05:00
Kevin F
83007cb28d Finished loading identities from blocks 2022-09-01 21:31:04 -05:00
Kevin F
57b1e07715 Finished identity serialization 2022-08-31 00:30:28 -05:00
Kevin F
bddddd7c5b Remove notifications for now 2022-08-22 12:27:06 -05:00
Kevin F
85b6f468fd Remove ID commands for now 2022-08-22 10:35:49 -05:00
Kevin F
5ca2c8d329 Corrected missing hashes 2022-08-22 10:19:39 -05:00
Kevin F
c0d3b367dc Get distance of trust with bfs 2022-08-18 00:12:01 -05:00
Kevin F
86615305d7 Fix tor peers not being removed from connection pool when they fail 2022-08-16 19:30:05 -05:00
Kevin F
69a31d1d83 Fixed high CPU usage when there are no outbound connections 2022-08-16 17:22:28 -05:00
Kevin F
954f5d793d fix log spamming 2022-08-16 17:11:56 -05:00
Kevin F
c95d4b2685 README cleanup 2022-08-16 16:24:13 -05:00
Kevin F
736549c1dc added dependencies for rpc 2022-08-16 16:08:39 -05:00
Kevin F
2deb9271dc README cleanup 2022-08-16 16:01:00 -05:00
Kevin F
189645d560 correct readme to current status 2022-08-16 10:46:23 -05:00
Kevin F
b59e79a21f Init wot plugin 2022-08-16 09:55:01 -05:00
Kevin F
3b8644fa8f Init wot plugin 2022-08-16 09:54:54 -05:00
Kevin F
b2ebc56419 Added RPC plugin scaffolding 2022-08-11 14:25:07 -05:00
Kevin F
bc71d12b77 Removed notifications requirements 2022-08-11 14:24:40 -05:00
Kevin F
264eeaa988 Started serializedAPI plugin 2022-08-09 19:02:37 -05:00
Kevin F
c880b6fa7a Removed webUI and unused god objects
Remove defunct requirements
Removed more defunct code
Prepare onionrvalues for new release
disable unixtransport by default
2022-08-06 12:01:32 -05:00
214 changed files with 3049 additions and 4529 deletions

View File

@ -1,12 +0,0 @@
# Incomplete List of Contributors
Onionr is created by a team of hard working volunteers.
In no order of importance, these people make Onionr happen:
* [Beardog (Kevin Froman)](https://www.chaoswebs.net/) - Project founder, owner and core developer
* [InvisaMage](https://invisamage.com/) - Web UI Bulma design
* [Arinerron](https://arinerron.com/) - Logger and config modules, testing and other contributions
* [Anhar Ismail](https://github.com/anharismail) - Created Onionr's logo
+ Other contributors and testers

View File

@ -1,4 +1,4 @@
FROM python:3.7
FROM python:3.10
EXPOSE 8080
USER root
@ -15,7 +15,7 @@ RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
locale-gen
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
ADD ./requirements.txt /app/requirements.txt
ADD ./requirements-x86-all-plugins.txt /app/requirements.txt
RUN pip3 install --require-hashes -r requirements.txt
#Add Onionr source
@ -28,4 +28,4 @@ RUN chmod g=u -R /app
USER 1000
ENV HOME=/app
CMD ["bash", "./run-onionr-node.sh"]
CMD ["bash", "./onionr.sh", "start"]

View File

@ -11,23 +11,23 @@
WIP anonymous social platform, mail, file sharing and marketplace
</p>
<img src="https://img.shields.io/badge/License-aGPLv3-yellow"> <img src='https://img.shields.io/badge/python%20version%20%F0%9F%90%8D-3.7+-blue'>
<img src="https://img.shields.io/badge/License-aGPLv3-yellow"> <img src='https://img.shields.io/badge/python%20version%20%F0%9F%90%8D-3.10+-blue'>
<a href='https://twitter.com/onionrnet'><img src='https://img.shields.io/twitter/follow/onionrnet?style=social'></a> - [Discord](https://discord.gg/DVF2bEAzrt) - Matrix: #onionr:amorgan.xyz
| | | |
| ----------- | ----------- | ----------- |
| [Install](#install-and-run-on-linux) | [Features](#main-features) | [Screenshots](#screenshots)|
| [Docs](#documentation)/[web copy](https://beardog108.github.io/onionr/) | [Get involved](#help-out) | [Onionr.net](https://onionr.net/)/[.onion](http://onionrbak72t5zhbzuey2fdkpczlvhowgcpqc6uoyrd3uxztzxwz5cyd.onion/) |
| [Docs](#documentation) | [Get involved](#help-out) | [Onionr.net](https://onionr.net/)/[.onion](http://onionrbak72t5zhbzuey2fdkpczlvhowgcpqc6uoyrd3uxztzxwz5cyd.onion/) |
---
**The main repository for this software is at https://git.VoidNet.tech/kev/onionr/**
**The main repository for this software is at https://gitlab.com/beardog/onionr/**
***Note that this README reflects the state of the rewrite, and not the original alpha network***
Mirrors [Gitlab](https://gitlab.com/beardog/onionr)
Mirrors [Gitea](https://git.voidnet.tech/kev/onionr)
Onionr ("Onion Relay") is a decentralized/distributed peer-to-peer communication network, designed to be anonymous and resistant to (meta)data analysis, spam, and corruption.
@ -84,14 +84,13 @@ Master may be unstable, you should use the latest release tag. (checkout via git
`$ sudo apt install python3-pip python3-dev tor`
* Have python3.7+, python3-pip, Tor (daemon, not browser) installed. python3-dev is recommended.
* Have python3.10, python3-pip, Tor (daemon, not browser) installed. python3-dev is recommended.
* You may need build-essentials or the equivalent of your platform
* Clone the git repo: `$ git clone https://gitlab.com/beardog/onionr --tags`
* cd into install direction: `$ cd onionr/`
* Install the Python dependencies ([virtualenv strongly recommended](https://virtualenv.pypa.io/en/stable/userguide/)): `$ pip3 install --require-hashes -r requirements.txt` (on ARM64 devices like Raspberry Pi 4's use requirements-ARM.txt instead.)
* (Optional): Install desktop notification dependencies: `$ pip3 install --require-hashes -r requirements-notifications.txt`
* Install the Python dependencies ([virtualenv strongly recommended](https://virtualenv.pypa.io/en/stable/userguide/)): `$ pip3 install --require-hashes -r requirements-x86-all-plugins.txt`
(--require-hashes is intended to prevent exploitation via compromise of PyPi/CA certificates)
Require-hashes is suggested for supply-chain security but is optional. The hashes are not correct for ARM machines. If you are just running a node or want a bare-bones install you can use requirements-base-x86.txt and selectively install the requirements.txt files in static-data/official-plugins/ subdirectories
## Run Onionr

View File

@ -6,32 +6,32 @@
* [ X ] Implement new block format with verifiable delay function
* [ ] Implement overhauled gossip system with dandelion++
* [ X ] Implement overhauled gossip system with dandelion++
The new system is separated from the underlying networks used and makes it much easier to implement new transport methods. Dandelion++ is also better than the old block mixing we did.
* [ ] Revamped key/encrypted messaging (encrypted blocks)
* [ ] Restore webUI as a plugin
* [ ] Restore static site/file sharing plugin
* [ ] Restore/reimplement mail plugin
* [ ] Restore/reimplement friends plugin
* [ ] Refresh test suite
## Misc
* [ ] Spruce up documentation
* [ ] Restore LAN transport
* [ ] Restore webUI as a plugin
* [ ] Restore static site/file sharing plugin
* [ ] Restore/reimplement mail plugin
* [ ] Restore/reimplement friends plugin
* [ ] Refresh test suite
* [ ] Revamped key/encrypted messaging (encrypted blocks)
## Web of trust release (10.0)
## Web of trust release (~10.0)
To facilitate the below market plugin/application, Onionr will need a web of trust system.
* [ ] Web of trust plugin or module
## Market Plugin Release (10.1)
## Market Plugin Release (~10.1)
The Onionr team believes the Monero community is currently lacking a good p2p market, and as such we hope to build a solution using Onionr as a transport. This may be a separate project and as opposed to a plugin.

View File

@ -1,11 +1,8 @@
PyNaCl==1.5.0
PySocks==1.7.1
stem==1.8.0
unpaddedbase32==0.2.0
niceware==0.2.1
psutil==5.9.1
filenuke==0.0.0
ujson==5.4.0
cffi==1.15.1
onionrblocks==7.0.0
ordered-set==4.1.0
ordered-set==4.1.0
json-rpc==1.13.0

View File

@ -1,124 +0,0 @@
# Onionr HTTP API
All HTTP interfaces in the Onionr reference client use the [Flask](http://flask.pocoo.org/) web framework with the [gevent](http://www.gevent.org/) WSGI server.
## Client & Public difference
The client API server is a locked down interface intended for authenticated local communication.
The public API server is available only remotely from Tor & I2P. It is the interface in which peers use to communicate with one another.
# Client API
Please note: endpoints that simply provide static web app files are not documented here.
* /serviceactive/pubkey
- Methods: GET
- Returns true or false based on if a given public key has an active direct connection service.
* /queueResponseAdd/key (DEPRECATED)
- Methods: POST
- Accepts form key 'data' to set queue response information from a plugin
- Returns success if no error occurs
* /queueResponse/key (DEPRECATED)
- Methods: GET
- Returns the queue response for a key. Returns failure with a 404 code if a code is not set.
* /ping
- Methods: GET
- Returns "pong!"
* /getblocksbytype/type
- Methods: GET
- Returns a list of stored blocks by a given type
* /getblockbody/hash
- Methods: GET
- Returns the main data section of a block
* /getblockdata/hash
- Methods: GET
- Returns the entire data contents of a block, including metadata.
* /getblockheader/hash
- Methods: GET
- Returns the header (metadata section) of a block.
* /gethidden/
- Methods: GET
- Returns line separated list of hidden blocks
* /hitcount
- Methods: GET
- Return the amount of requests the public api server has received this session
* /lastconnect
- Methods: GET
- Returns the epoch timestamp of when the last incoming connection to the public API server was logged
* /site/hash
- Methods: GET
- Returns HTML content out of a block
* /waitforshare/hash
- Methods: POST
- Prevents the public API server from listing or sharing a block until it has been uploaded to at least 1 peer.
* /shutdown
- Methods: GET
- Shutdown Onionr. You should probably use /shutdownclean instead.
* /shutdownclean
- Methods: GET
- Tells the communicator daemon to shutdown Onionr. Slower but cleaner.
* /getstats
- Methods: GET
- Returns some JSON serialized statistics
* /getuptime
- Methods: GET
- Returns uptime in seconds
* /getActivePubkey
- Methods: GET
- Returns the current active public key in base32 format
* /getHumanReadable/pubkey
- Methods: GET
- Echos the specified public key in mnemonic format
* /insertblock
- Methods: POST
- Accepts JSON data for creating a new block. 'message' contains the block data, 'to' specifies the peer's public key to encrypt the data to, 'sign' is a boolean for signing the message.
* /torready
- Methods: POST
- Returns boolean if Tor is started or not
# Public API
v0
* /
- Methods: GET
- Returns a basic HTML informational banner describing Onionr.
* /getblocklist
- Methods: GET
- URI Parameters:
- date: unix epoch timestamp for offset
- Returns a list of block hashes stored on the node since an offset (all blocks if no timestamp is specified)
* /getdata/block-hash
- Methods: GET
- Returns data for a block based on a provided hash
* /www/file-path
- Methods: GET
- Returns file data. Intended for manually sharing file data directly from an Onionr node.
* /ping
- Methods: GET
- Returns 'pong!'
* /pex
- Methods: GET
- Returns a list of peer addresses reached within recent time
* /announce
- Methods: POST
- Accepts form data for 'node' (valid node address) and 'random' which is a nonce when hashed (blake2b_256) in the format `hash(peerAddress+serverAddress+nonce)`, begins with at least 5 zeros.
- Returns 200 with 'Success' if no error occurs. If the post is invalid, 'failure' with code 406 is returned.
* /upload
- Methods: POST
- Accepts form data for 'block' as a 'file' upload.
- Returns 200 with 'success' if no error occurs. If the block cannot be accepted, 'failure' with 400 is returned.
# Direct Connection API
These are constant endpoints available on direct connection servers. Plugin endpoints for direct connections are not documented here.
* /ping
- Methods: GET
- Returns 200 with 'pong!'
* /close
- Methods: GET
- Kills the direct connection server, destroying the onion address.
- Returns 200 with 'goodbye'

View File

@ -2,6 +2,8 @@
ORIG_ONIONR_RUN_DIR=`pwd`
export ORIG_ONIONR_RUN_DIR
export PYTHONDONTWRITEBYTECODE=1
export PYTHONUNBUFFERED=1
export PYTHONOPTIMIZE="true"
cd "$(dirname "$0")"
cd src
./__init__.py "$@"

View File

@ -1,392 +0,0 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --generate-hashes --output-file=requirements-ARM.txt requirements.in
#
--extra-index-url https://www.piwheels.org/simple
certifi==2020.12.5 \
--hash=sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c \
--hash=sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830
# via requests
cffi==1.14.4 \
--hash=sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e \
--hash=sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d \
--hash=sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a \
--hash=sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec \
--hash=sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362 \
--hash=sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668 \
--hash=sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c \
--hash=sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b \
--hash=sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06 \
--hash=sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698 \
--hash=sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2 \
--hash=sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c \
--hash=sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7 \
--hash=sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009 \
--hash=sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03 \
--hash=sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b \
--hash=sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909 \
--hash=sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53 \
--hash=sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35 \
--hash=sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26 \
--hash=sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b \
--hash=sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01 \
--hash=sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb \
--hash=sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293 \
--hash=sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd \
--hash=sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d \
--hash=sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3 \
--hash=sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d \
--hash=sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e \
--hash=sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca \
--hash=sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d \
--hash=sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775 \
--hash=sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375 \
--hash=sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b \
--hash=sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b \
--hash=sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f
# via
# -r requirements.in
# pynacl
chardet==4.0.0 \
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
# via requests
click==7.1.2 \
--hash=sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a \
--hash=sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc
# via flask
deadsimplekv==0.3.2 \
--hash=sha256:a725f4a9d1156ebb66b7535ac150006881e0365b715e34e3709214827b8b0c4c \
--hash=sha256:df00262d26c3dcfecb710425a7413059480d8cf026216042d7cbffb8514818b2
# via -r requirements.in
filenuke==0.0.0 \
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f
# via -r requirements.in
flask==1.1.2 \
--hash=sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060 \
--hash=sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557
# via -r requirements.in
gevent==20.9.0 \
--hash=sha256:10110d4881aec04f218c316cb796b18c8b2cac67ae0eb5b0c5780056757268a2 \
--hash=sha256:1628a403fc9c3ea9b35924638a4d4fbe236f60ecdf4e22ed133fbbaf0bc7cb6b \
--hash=sha256:1cfa3674866294623e324fa5b76eba7b96744d1956a605cfe24d26c5cd890f91 \
--hash=sha256:2269574444113cb4ca1c1808ab9460a87fe25e1c34a6e36d975d4af46e4afff9 \
--hash=sha256:283a021a2e14adfad718346f18982b80569d9c3a59e97cfae1b7d4c5b017941a \
--hash=sha256:2aa70726ad1883fe7c17774e5ccc91ac6e30334efa29bafb9b8fe8ca6091b219 \
--hash=sha256:315a63a35068183dfb9bc0331c7bb3c265ee7db8a11797cbe98dadbdb45b5d35 \
--hash=sha256:324808a8558c733f7a9734525483795d52ca3bbd5662b24b361d81c075414b1f \
--hash=sha256:33a63f230755c6813fca39d9cea2a8894df32df2ee58fd69d8bf8fcc1d8e018e \
--hash=sha256:5f6d48051d336561ec08995431ee4d265ac723a64bba99cc58c3eb1a4d4f5c8d \
--hash=sha256:8d338cd6d040fe2607e5305dd7991b5960b3780ae01f804c2ac5760d31d3b2c6 \
--hash=sha256:906175e3fb25f377a0b581e79d3ed5a7d925c136ff92fd022bb3013e25f5f3a9 \
--hash=sha256:93980e51dd2e5f81899d644a0b6ef4a73008c679fcedd50e3b21cc3451ba2424 \
--hash=sha256:9bb477f514cf39dc20651b479bf1ad4f38b9a679be2bfa3e162ec0c3785dfa2a \
--hash=sha256:a8733a01974433d91308f8c44fa6cc13428b15bb39d46540657e260ff8852cb1 \
--hash=sha256:adbb267067f56696b2babced3d0856aa39dcf14b8ccd2dffa1fab587b00c6f80 \
--hash=sha256:afc177c37de41ce9c27d351ac84cbaf34407effcab5d6641645838f39d365be1 \
--hash=sha256:b07fcbca3e819296979d82fac3d8b44f0d5ced57b9a04dffcfd194da99c8eb2d \
--hash=sha256:b2948566003a1030e47507755fe1f446995e8671c0c67571091539e01faf94cc \
--hash=sha256:db208e74a32cff7f55f5aa1ba5d7d1c1a086a6325c8702ae78a5c741155552ff \
--hash=sha256:dd4c6b2f540b25c3d0f277a725bc1a900ce30a681b90a081216e31f814be453b \
--hash=sha256:e11de4b4d107ca2f35000eb08e9c4c4621c153103b400f48a9ea95b96d8c7e0b \
--hash=sha256:eba19bae532d0c48d489fa16815b242ce074b1f4b63e8a8e663232cbe311ead9 \
--hash=sha256:fb33dc1ab27557bccd64ad4bf81e68c8b0d780fe937b1e2c0814558798137229
# via -r requirements.in
greenlet==1.0.0 \
--hash=sha256:0a77691f0080c9da8dfc81e23f4e3cffa5accf0f5b56478951016d7cfead9196 \
--hash=sha256:0ddd77586553e3daf439aa88b6642c5f252f7ef79a39271c25b1d4bf1b7cbb85 \
--hash=sha256:111cfd92d78f2af0bc7317452bd93a477128af6327332ebf3c2be7df99566683 \
--hash=sha256:122c63ba795fdba4fc19c744df6277d9cfd913ed53d1a286f12189a0265316dd \
--hash=sha256:181300f826625b7fd1182205b830642926f52bd8cdb08b34574c9d5b2b1813f7 \
--hash=sha256:1a1ada42a1fd2607d232ae11a7b3195735edaa49ea787a6d9e6a53afaf6f3476 \
--hash=sha256:1bb80c71de788b36cefb0c3bb6bfab306ba75073dbde2829c858dc3ad70f867c \
--hash=sha256:1d1d4473ecb1c1d31ce8fd8d91e4da1b1f64d425c1dc965edc4ed2a63cfa67b2 \
--hash=sha256:292e801fcb3a0b3a12d8c603c7cf340659ea27fd73c98683e75800d9fd8f704c \
--hash=sha256:2c65320774a8cd5fdb6e117c13afa91c4707548282464a18cf80243cf976b3e6 \
--hash=sha256:4365eccd68e72564c776418c53ce3c5af402bc526fe0653722bc89efd85bf12d \
--hash=sha256:5352c15c1d91d22902582e891f27728d8dac3bd5e0ee565b6a9f575355e6d92f \
--hash=sha256:58ca0f078d1c135ecf1879d50711f925ee238fe773dfe44e206d7d126f5bc664 \
--hash=sha256:5d4030b04061fdf4cbc446008e238e44936d77a04b2b32f804688ad64197953c \
--hash=sha256:5d69bbd9547d3bc49f8a545db7a0bd69f407badd2ff0f6e1a163680b5841d2b0 \
--hash=sha256:5f297cb343114b33a13755032ecf7109b07b9a0020e841d1c3cedff6602cc139 \
--hash=sha256:62afad6e5fd70f34d773ffcbb7c22657e1d46d7fd7c95a43361de979f0a45aef \
--hash=sha256:647ba1df86d025f5a34043451d7c4a9f05f240bee06277a524daad11f997d1e7 \
--hash=sha256:719e169c79255816cdcf6dccd9ed2d089a72a9f6c42273aae12d55e8d35bdcf8 \
--hash=sha256:7cd5a237f241f2764324396e06298b5dee0df580cf06ef4ada0ff9bff851286c \
--hash=sha256:875d4c60a6299f55df1c3bb870ebe6dcb7db28c165ab9ea6cdc5d5af36bb33ce \
--hash=sha256:90b6a25841488cf2cb1c8623a53e6879573010a669455046df5f029d93db51b7 \
--hash=sha256:94620ed996a7632723a424bccb84b07e7b861ab7bb06a5aeb041c111dd723d36 \
--hash=sha256:b5f1b333015d53d4b381745f5de842f19fe59728b65f0fbb662dafbe2018c3a5 \
--hash=sha256:c5b22b31c947ad8b6964d4ed66776bcae986f73669ba50620162ba7c832a6b6a \
--hash=sha256:c93d1a71c3fe222308939b2e516c07f35a849c5047f0197442a4d6fbcb4128ee \
--hash=sha256:cdb90267650c1edb54459cdb51dab865f6c6594c3a47ebd441bc493360c7af70 \
--hash=sha256:cfd06e0f0cc8db2a854137bd79154b61ecd940dce96fad0cba23fe31de0b793c \
--hash=sha256:d3789c1c394944084b5e57c192889985a9f23bd985f6d15728c745d380318128 \
--hash=sha256:da7d09ad0f24270b20f77d56934e196e982af0d0a2446120cb772be4e060e1a2 \
--hash=sha256:df3e83323268594fa9755480a442cabfe8d82b21aba815a71acf1bb6c1776218 \
--hash=sha256:df8053867c831b2643b2c489fe1d62049a98566b1646b194cc815f13e27b90df \
--hash=sha256:e1128e022d8dce375362e063754e129750323b67454cac5600008aad9f54139e \
--hash=sha256:e6e9fdaf6c90d02b95e6b0709aeb1aba5affbbb9ccaea5502f8638e4323206be \
--hash=sha256:eac8803c9ad1817ce3d8d15d1bb82c2da3feda6bee1153eec5c58fa6e5d3f770 \
--hash=sha256:eb333b90036358a0e2c57373f72e7648d7207b76ef0bd00a4f7daad1f79f5203 \
--hash=sha256:ed1d1351f05e795a527abc04a0d82e9aecd3bdf9f46662c36ff47b0b00ecaf06 \
--hash=sha256:f3dc68272990849132d6698f7dc6df2ab62a88b0d36e54702a8fd16c0490e44f \
--hash=sha256:f59eded163d9752fd49978e0bab7a1ff21b1b8d25c05f0995d140cc08ac83379 \
--hash=sha256:f5e2d36c86c7b03c94b8459c3bd2c9fe2c7dab4b258b8885617d44a22e453fb7 \
--hash=sha256:f6f65bf54215e4ebf6b01e4bb94c49180a589573df643735107056f7a910275b \
--hash=sha256:f8450d5ef759dbe59f84f2c9f77491bb3d3c44bc1a573746daf086e70b14c243 \
--hash=sha256:f97d83049715fd9dec7911860ecf0e17b48d8725de01e45de07d8ac0bd5bc378
# via gevent
idna==2.10 \
--hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \
--hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0
# via requests
itsdangerous==1.1.0 \
--hash=sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19 \
--hash=sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749
# via flask
jinja2==2.11.2 \
--hash=sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0 \
--hash=sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035
# via flask
markupsafe==1.1.1 \
--hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \
--hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \
--hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \
--hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \
--hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \
--hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \
--hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b \
--hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \
--hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \
--hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \
--hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \
--hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \
--hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \
--hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \
--hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \
--hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \
--hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \
--hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \
--hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \
--hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \
--hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \
--hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \
--hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \
--hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \
--hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \
--hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \
--hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \
--hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \
--hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \
--hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \
--hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \
--hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \
--hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be
# via jinja2
niceware==0.2.1 \
--hash=sha256:0f8b192f2a1e800e068474f6e208be9c7e2857664b33a96f4045340de4e5c69c \
--hash=sha256:cf2dc0e1567d36d067c61b32fed0f1b9c4534ed511f9eeead4ba548d03b5c9eb
# via -r requirements.in
psutil==5.8.0 \
--hash=sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64 \
--hash=sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131 \
--hash=sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c \
--hash=sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6 \
--hash=sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023 \
--hash=sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df \
--hash=sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394 \
--hash=sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4 \
--hash=sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b \
--hash=sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2 \
--hash=sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d \
--hash=sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65 \
--hash=sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d \
--hash=sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef \
--hash=sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7 \
--hash=sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60 \
--hash=sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6 \
--hash=sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8 \
--hash=sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b \
--hash=sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d \
--hash=sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac \
--hash=sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935 \
--hash=sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d \
--hash=sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28 \
--hash=sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876 \
--hash=sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0 \
--hash=sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3 \
--hash=sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563
# via -r requirements.in
pycparser==2.20 \
--hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \
--hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705
# via cffi
pynacl==1.4.0 \
--hash=sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4 \
--hash=sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4 \
--hash=sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574 \
--hash=sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d \
--hash=sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634 \
--hash=sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25 \
--hash=sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f \
--hash=sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505 \
--hash=sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122 \
--hash=sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7 \
--hash=sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420 \
--hash=sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f \
--hash=sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96 \
--hash=sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6 \
--hash=sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6 \
--hash=sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514 \
--hash=sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff \
--hash=sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80
# via -r requirements.in
pysocks==1.7.1 \
--hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
# via -r requirements.in
requests==2.25.1 \
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
# via
# -r requirements.in
# streamedrequests
six==1.15.0 \
--hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \
--hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced
# via pynacl
stem==1.8.0 \
--hash=sha256:a0b48ea6224e95f22aa34c0bc3415f0eb4667ddeae3dfb5e32a6920c185568c2
# via -r requirements.in
streamedrequests==1.0.3 \
--hash=sha256:4388ffc0ee94dda719dafc4324b8ddd108cb2231ec59871de79e2592bf4eef0a \
--hash=sha256:ee68417a1522e75c35b1b2d5f3b6f7e76a3a1a6c0ef5e0c573d08307910079d8
# via -r requirements.in
toomanyobjs==1.1.0 \
--hash=sha256:99e27468f9dad19127be9e2fb086b42acd69aed9ad7e63cef74d6e4389be0534
# via -r requirements.in
ujson==4.0.1 \
--hash=sha256:078808c385036cba73cad96f498310c61e9b5ae5ac9ea01e7c3996ece544b556 \
--hash=sha256:0a2e1b211714eb1ec0772a013ec9967f8f95f21c84e8f46382e9f8a32ae781fe \
--hash=sha256:0f412c3f59b1ab0f40018235224ca0cf29232d0201ff5085618565a8a9c810ed \
--hash=sha256:26cf6241b36ff5ce4539ae687b6b02673109c5e3efc96148806a7873eaa229d3 \
--hash=sha256:2b2d9264ac76aeb11f590f7a1ccff0689ba1313adacbb6d38d3b15f21a392897 \
--hash=sha256:4f12b0b4e235b35d49f15227b0a827e614c52dda903c58a8f5523936c233dfc7 \
--hash=sha256:4fe8c6112b732cba5a722f7cbe22f18d405f6f44415794a5b46473a477635233 \
--hash=sha256:51480048373cf97a6b97fcd70c3586ca0a31f27e22ab680fb14c1f22bedbf743 \
--hash=sha256:568bb3e7f035006147af4ce3a9ced7d126c92e1a8607c7b2266007b1c1162c53 \
--hash=sha256:5fe1536465b1c86e32a47113abd3178001b7c2dcd61f95f336fe2febf4661e74 \
--hash=sha256:71703a269f074ff65b9d7746662e4b3e76a4af443e532218af1e8ce15d9b1e7b \
--hash=sha256:7a1545ac2476db4cc1f0f236603ccbb50991fc1bba480cda1bc06348cc2a2bf0 \
--hash=sha256:a5200a68f1dcf3ce275e1cefbcfa3914b70c2b5e2f71c2e31556aa1f7244c845 \
--hash=sha256:a618af22407baeadb3f046f81e7a5ee5e9f8b0b716d2b564f92276a54d26a823 \
--hash=sha256:a79bca47eafb31c74b38e68623bc9b2bb930cb48fab1af31c8f2cb68cf473421 \
--hash=sha256:b87379a3f8046d6d111762d81f3384bf38ab24b1535c841fe867a4a097d84523 \
--hash=sha256:bd4c77aee3ffb920e2dbc21a9e0c7945a400557ce671cfd57dbd569f5ebc619d \
--hash=sha256:c354c1617b0a4378b6279d0cd511b769500cf3fa7c42e8e004cbbbb6b4c2a875 \
--hash=sha256:c604024bd853b5df6be7d933e934da8dd139e6159564db7c55b92a9937678093 \
--hash=sha256:e7ab24942b2d57920d75b817b8eead293026db003247e26f99506bdad86c61b4 \
--hash=sha256:f8a60928737a9a47e692fcd661ef2b5d75ba22c7c930025bd95e338f2a6e15bc
# via -r requirements.in
unpaddedbase32==0.2.0 \
--hash=sha256:4aacee75f8fd6c8cf129842ecba45ca59c11bfb13dae19d86f32b48fa3715403 \
--hash=sha256:b7b780c31d27d55e66abf6c221216a35690ee8892c2daacff7f2528e229bd9c3
# via -r requirements.in
urllib3==1.25.11 \
--hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 \
--hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e
# via
# -r requirements.in
# requests
watchdog==1.0.2 \
--hash=sha256:016b01495b9c55b5d4126ed8ae75d93ea0d99377084107c33162df52887cee18 \
--hash=sha256:101532b8db506559e52a9b5d75a308729b3f68264d930670e6155c976d0e52a0 \
--hash=sha256:27d9b4666938d5d40afdcdf2c751781e9ce36320788b70208d0f87f7401caf93 \
--hash=sha256:2f1ade0d0802503fda4340374d333408831cff23da66d7e711e279ba50fe6c4a \
--hash=sha256:376cbc2a35c0392b0fe7ff16fbc1b303fd99d4dd9911ab5581ee9d69adc88982 \
--hash=sha256:57f05e55aa603c3b053eed7e679f0a83873c540255b88d58c6223c7493833bac \
--hash=sha256:5f1f3b65142175366ba94c64d8d4c8f4015825e0beaacee1c301823266b47b9b \
--hash=sha256:602dbd9498592eacc42e0632c19781c3df1728ef9cbab555fab6778effc29eeb \
--hash=sha256:68744de2003a5ea2dfbb104f9a74192cf381334a9e2c0ed2bbe1581828d50b61 \
--hash=sha256:85e6574395aa6c1e14e0f030d9d7f35c2340a6cf95d5671354ce876ac3ffdd4d \
--hash=sha256:b1d723852ce90a14abf0ec0ca9e80689d9509ee4c9ee27163118d87b564a12ac \
--hash=sha256:d948ad9ab9aba705f9836625b32e965b9ae607284811cd98334423f659ea537a \
--hash=sha256:e2a531e71be7b5cc3499ae2d1494d51b6a26684bcc7c3146f63c810c00e8a3cc \
--hash=sha256:e7c73edef48f4ceeebb987317a67e0080e5c9228601ff67b3c4062fa020403c7 \
--hash=sha256:ee21aeebe6b3e51e4ba64564c94cee8dbe7438b9cb60f0bb350c4fa70d1b52c2 \
--hash=sha256:f1d0e878fd69129d0d68b87cee5d9543f20d8018e82998efb79f7e412d42154a \
--hash=sha256:f84146f7864339c8addf2c2b9903271df21d18d2c721e9a77f779493234a82b5
# via -r requirements.in
werkzeug==1.0.1 \
--hash=sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43 \
--hash=sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c
# via flask
zope.event==4.5.0 \
--hash=sha256:2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42 \
--hash=sha256:5e76517f5b9b119acf37ca8819781db6c16ea433f7e2062c4afc2b6fbedb1330
# via gevent
zope.interface==5.2.0 \
--hash=sha256:05a97ba92c1c7c26f25c9f671aa1ef85ffead6cdad13770e5b689cf983adc7e1 \
--hash=sha256:07d61722dd7d85547b7c6b0f5486b4338001fab349f2ac5cabc0b7182eb3425d \
--hash=sha256:0a990dcc97806e5980bbb54b2e46b9cde9e48932d8e6984daf71ef1745516123 \
--hash=sha256:150e8bcb7253a34a4535aeea3de36c0bb3b1a6a47a183a95d65a194b3e07f232 \
--hash=sha256:1743bcfe45af8846b775086471c28258f4c6e9ee8ef37484de4495f15a98b549 \
--hash=sha256:1b5f6c8fff4ed32aa2dd43e84061bc8346f32d3ba6ad6e58f088fe109608f102 \
--hash=sha256:21e49123f375703cf824214939d39df0af62c47d122d955b2a8d9153ea08cfd5 \
--hash=sha256:21f579134a47083ffb5ddd1307f0405c91aa8b61ad4be6fd5af0171474fe0c45 \
--hash=sha256:27c267dc38a0f0079e96a2945ee65786d38ef111e413c702fbaaacbab6361d00 \
--hash=sha256:299bde0ab9e5c4a92f01a152b7fbabb460f31343f1416f9b7b983167ab1e33bc \
--hash=sha256:2ab88d8f228f803fcb8cb7d222c579d13dab2d3622c51e8cf321280da01102a7 \
--hash=sha256:2ced4c35061eea623bc84c7711eedce8ecc3c2c51cd9c6afa6290df3bae9e104 \
--hash=sha256:2dcab01c660983ba5e5a612e0c935141ccbee67d2e2e14b833e01c2354bd8034 \
--hash=sha256:32546af61a9a9b141ca38d971aa6eb9800450fa6620ce6323cc30eec447861f3 \
--hash=sha256:32b40a4c46d199827d79c86bb8cb88b1bbb764f127876f2cb6f3a47f63dbada3 \
--hash=sha256:3cc94c69f6bd48ed86e8e24f358cb75095c8129827df1298518ab860115269a4 \
--hash=sha256:42b278ac0989d6f5cf58d7e0828ea6b5951464e3cf2ff229dd09a96cb6ba0c86 \
--hash=sha256:495b63fd0302f282ee6c1e6ea0f1c12cb3d1a49c8292d27287f01845ff252a96 \
--hash=sha256:4af87cdc0d4b14e600e6d3d09793dce3b7171348a094ba818e2a68ae7ee67546 \
--hash=sha256:4b94df9f2fdde7b9314321bab8448e6ad5a23b80542dcab53e329527d4099dcb \
--hash=sha256:4c48ddb63e2b20fba4c6a2bf81b4d49e99b6d4587fb67a6cd33a2c1f003af3e3 \
--hash=sha256:4df9afd17bd5477e9f8c8b6bb8507e18dd0f8b4efe73bb99729ff203279e9e3b \
--hash=sha256:518950fe6a5d56f94ba125107895f938a4f34f704c658986eae8255edb41163b \
--hash=sha256:538298e4e113ccb8b41658d5a4b605bebe75e46a30ceca22a5a289cf02c80bec \
--hash=sha256:55465121e72e208a7b69b53de791402affe6165083b2ea71b892728bd19ba9ae \
--hash=sha256:588384d70a0f19b47409cfdb10e0c27c20e4293b74fc891df3d8eb47782b8b3e \
--hash=sha256:6278c080d4afffc9016e14325f8734456831124e8c12caa754fd544435c08386 \
--hash=sha256:64ea6c221aeee4796860405e1aedec63424cda4202a7ad27a5066876db5b0fd2 \
--hash=sha256:681dbb33e2b40262b33fd383bae63c36d33fd79fa1a8e4092945430744ffd34a \
--hash=sha256:6936aa9da390402d646a32a6a38d5409c2d2afb2950f045a7d02ab25a4e7d08d \
--hash=sha256:778d0ec38bbd288b150a3ae363c8ffd88d2207a756842495e9bffd8a8afbc89a \
--hash=sha256:8251f06a77985a2729a8bdbefbae79ee78567dddc3acbd499b87e705ca59fe24 \
--hash=sha256:83b4aa5344cce005a9cff5d0321b2e318e871cc1dfc793b66c32dd4f59e9770d \
--hash=sha256:844fad925ac5c2ad4faaceb3b2520ad016b5280105c6e16e79838cf951903a7b \
--hash=sha256:8ceb3667dd13b8133f2e4d637b5b00f240f066448e2aa89a41f4c2d78a26ce50 \
--hash=sha256:92dc0fb79675882d0b6138be4bf0cec7ea7c7eede60aaca78303d8e8dbdaa523 \
--hash=sha256:9789bd945e9f5bd026ed3f5b453d640befb8b1fc33a779c1fe8d3eb21fe3fb4a \
--hash=sha256:a2b6d6eb693bc2fc6c484f2e5d93bd0b0da803fa77bf974f160533e555e4d095 \
--hash=sha256:aab9f1e34d810feb00bf841993552b8fcc6ae71d473c505381627143d0018a6a \
--hash=sha256:abb61afd84f23099ac6099d804cdba9bd3b902aaaded3ffff47e490b0a495520 \
--hash=sha256:adf9ee115ae8ff8b6da4b854b4152f253b390ba64407a22d75456fe07dcbda65 \
--hash=sha256:aedc6c672b351afe6dfe17ff83ee5e7eb6ed44718f879a9328a68bdb20b57e11 \
--hash=sha256:b7a00ecb1434f8183395fac5366a21ee73d14900082ca37cf74993cf46baa56c \
--hash=sha256:ba32f4a91c1cb7314c429b03afbf87b1fff4fb1c8db32260e7310104bd77f0c7 \
--hash=sha256:cbd0f2cbd8689861209cd89141371d3a22a11613304d1f0736492590aa0ab332 \
--hash=sha256:e4bc372b953bf6cec65a8d48482ba574f6e051621d157cf224227dbb55486b1e \
--hash=sha256:eccac3d9aadc68e994b6d228cb0c8919fc47a5350d85a1b4d3d81d1e98baf40c \
--hash=sha256:efd550b3da28195746bb43bd1d815058181a7ca6d9d6aa89dd37f5eefe2cacb7 \
--hash=sha256:efef581c8ba4d990770875e1a2218e856849d32ada2680e53aebc5d154a17e20 \
--hash=sha256:f057897711a630a0b7a6a03f1acf379b6ba25d37dc5dc217a97191984ba7f2fc \
--hash=sha256:f37d45fab14ffef9d33a0dc3bc59ce0c5313e2253323312d47739192da94f5fd \
--hash=sha256:f44906f70205d456d503105023041f1e63aece7623b31c390a0103db4de17537
# via gevent
# WARNING: The following packages were not pinned, but pip requires them to be
# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
# setuptools

270
requirements-base-x86.txt Normal file
View File

@ -0,0 +1,270 @@
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile --generate-hashes --output-file=requirements-base-x86.txt requirements-base.in
#
cffi==1.15.1 \
--hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \
--hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \
--hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \
--hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \
--hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \
--hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \
--hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \
--hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \
--hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \
--hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \
--hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \
--hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \
--hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \
--hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \
--hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \
--hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \
--hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \
--hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \
--hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \
--hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \
--hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \
--hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \
--hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \
--hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \
--hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \
--hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \
--hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \
--hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \
--hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \
--hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \
--hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \
--hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \
--hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \
--hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \
--hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \
--hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \
--hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \
--hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \
--hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \
--hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \
--hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \
--hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \
--hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \
--hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \
--hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \
--hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \
--hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \
--hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \
--hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \
--hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \
--hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \
--hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \
--hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \
--hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \
--hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \
--hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \
--hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \
--hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \
--hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \
--hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \
--hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \
--hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \
--hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \
--hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0
# via pynacl
filenuke==0.0.0 \
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f
# via -r requirements-base.in
kasten==3.0.0 \
--hash=sha256:52894af46d6e1339f0d5fa8961892b292f99176848bce11877fe4a435b6782e5 \
--hash=sha256:b22ebdc5f475c2ef9ab74abc36552add0b37732a7ce2be6bd7977ee41b2163b4
# via onionrblocks
mimcvdf==1.2.1 \
--hash=sha256:7c837c46cfb9dce4ba895bc706a69646d4d5185c66aeaa333b5cfaa9a7d06dc4
# via kasten
msgpack==1.0.4 \
--hash=sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467 \
--hash=sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae \
--hash=sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92 \
--hash=sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef \
--hash=sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624 \
--hash=sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227 \
--hash=sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88 \
--hash=sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9 \
--hash=sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8 \
--hash=sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd \
--hash=sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6 \
--hash=sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55 \
--hash=sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e \
--hash=sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2 \
--hash=sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44 \
--hash=sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6 \
--hash=sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9 \
--hash=sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab \
--hash=sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae \
--hash=sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa \
--hash=sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9 \
--hash=sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e \
--hash=sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250 \
--hash=sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce \
--hash=sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075 \
--hash=sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236 \
--hash=sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae \
--hash=sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e \
--hash=sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f \
--hash=sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08 \
--hash=sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6 \
--hash=sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d \
--hash=sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43 \
--hash=sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1 \
--hash=sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6 \
--hash=sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0 \
--hash=sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c \
--hash=sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff \
--hash=sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db \
--hash=sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243 \
--hash=sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661 \
--hash=sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba \
--hash=sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e \
--hash=sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb \
--hash=sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52 \
--hash=sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6 \
--hash=sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1 \
--hash=sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f \
--hash=sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da \
--hash=sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f \
--hash=sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c \
--hash=sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8
# via kasten
onionrblocks==7.0.0 \
--hash=sha256:53e90964371076d9daf2ed0790b21f174ef3321f4f1808209cc6dd9b7ff6d8ff \
--hash=sha256:54af28d0be856209525646c4ef9f977f95f0ae1329b2cc023b351317c9d0eef7
# via -r requirements-base.in
ordered-set==4.1.0 \
--hash=sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562 \
--hash=sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8
# via -r requirements-base.in
psutil==5.9.3 \
--hash=sha256:07d880053c6461c9b89cd5d4808f3b8336665fa3acdefd6777662c5ed73a851a \
--hash=sha256:12500d761ac091f2426567f19f95fd3f15a197d96befb44a5c1e3cbe6db5752c \
--hash=sha256:1b540599481c73408f6b392cdffef5b01e8ff7a2ac8caae0a91b8222e88e8f1e \
--hash=sha256:35feafe232d1aaf35d51bd42790cbccb882456f9f18cdc411532902370d660df \
--hash=sha256:3a7826e68b0cf4ce2c1ee385d64eab7d70e3133171376cac53d7c1790357ec8f \
--hash=sha256:46907fa62acaac364fff0b8a9da7b360265d217e4fdeaca0a2397a6883dffba2 \
--hash=sha256:4bd4854f0c83aa84a5a40d3b5d0eb1f3c128f4146371e03baed4589fe4f3c931 \
--hash=sha256:538fcf6ae856b5e12d13d7da25ad67f02113c96f5989e6ad44422cb5994ca7fc \
--hash=sha256:547ebb02031fdada635452250ff39942db8310b5c4a8102dfe9384ee5791e650 \
--hash=sha256:5e8b50241dd3c2ed498507f87a6602825073c07f3b7e9560c58411c14fe1e1c9 \
--hash=sha256:5fa88e3d5d0b480602553d362c4b33a63e0c40bfea7312a7bf78799e01e0810b \
--hash=sha256:68fa227c32240c52982cb931801c5707a7f96dd8927f9102d6c7771ea1ff5698 \
--hash=sha256:6ced1ad823ecfa7d3ce26fe8aa4996e2e53fb49b7fed8ad81c80958501ec0619 \
--hash=sha256:71b1206e7909792d16933a0d2c1c7f04ae196186c51ba8567abae1d041f06dcb \
--hash=sha256:767ef4fa33acda16703725c0473a91e1832d296c37c63896c7153ba81698f1ab \
--hash=sha256:7ccfcdfea4fc4b0a02ca2c31de7fcd186beb9cff8207800e14ab66f79c773af6 \
--hash=sha256:7e4939ff75149b67aef77980409f156f0082fa36accc475d45c705bb00c6c16a \
--hash=sha256:828c9dc9478b34ab96be75c81942d8df0c2bb49edbb481f597314d92b6441d89 \
--hash=sha256:8a4e07611997acf178ad13b842377e3d8e9d0a5bac43ece9bfc22a96735d9a4f \
--hash=sha256:941a6c2c591da455d760121b44097781bc970be40e0e43081b9139da485ad5b7 \
--hash=sha256:9a4af6ed1094f867834f5f07acd1250605a0874169a5fcadbcec864aec2496a6 \
--hash=sha256:9ec296f565191f89c48f33d9544d8d82b0d2af7dd7d2d4e6319f27a818f8d1cc \
--hash=sha256:9ec95df684583b5596c82bb380c53a603bb051cf019d5c849c47e117c5064395 \
--hash=sha256:a04a1836894c8279e5e0a0127c0db8e198ca133d28be8a2a72b4db16f6cf99c1 \
--hash=sha256:a3d81165b8474087bb90ec4f333a638ccfd1d69d34a9b4a1a7eaac06648f9fbe \
--hash=sha256:b4a247cd3feaae39bb6085fcebf35b3b8ecd9b022db796d89c8f05067ca28e71 \
--hash=sha256:ba38cf9984d5462b506e239cf4bc24e84ead4b1d71a3be35e66dad0d13ded7c1 \
--hash=sha256:beb57d8a1ca0ae0eb3d08ccaceb77e1a6d93606f0e1754f0d60a6ebd5c288837 \
--hash=sha256:d266cd05bd4a95ca1c2b9b5aac50d249cf7c94a542f47e0b22928ddf8b80d1ef \
--hash=sha256:d8c3cc6bb76492133474e130a12351a325336c01c96a24aae731abf5a47fe088 \
--hash=sha256:db8e62016add2235cc87fb7ea000ede9e4ca0aa1f221b40cef049d02d5d2593d \
--hash=sha256:e7507f6c7b0262d3e7b0eeda15045bf5881f4ada70473b87bc7b7c93b992a7d7 \
--hash=sha256:ed15edb14f52925869250b1375f0ff58ca5c4fa8adefe4883cfb0737d32f5c02 \
--hash=sha256:f57d63a2b5beaf797b87024d018772439f9d3103a395627b77d17a8d72009543 \
--hash=sha256:fa5e32c7d9b60b2528108ade2929b115167fe98d59f89555574715054f50fa31 \
--hash=sha256:fe79b4ad4836e3da6c4650cb85a663b3a51aef22e1a829c384e18fae87e5e727
# via -r requirements-base.in
pycparser==2.21 \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
# via cffi
pynacl==1.5.0 \
--hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \
--hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \
--hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \
--hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \
--hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \
--hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \
--hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \
--hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \
--hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \
--hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543
# via onionrblocks
result==0.8.0 \
--hash=sha256:c48c909e92181a075ba358228a3fe161e26d205dad416ad81f27f23515a5626d \
--hash=sha256:d6a6258f32c057a4e0478999c6ce43dcadaf8ea435f58ac601ae2768f93ef243
# via -r requirements-base.in
ujson==5.5.0 \
--hash=sha256:0762a4fdf86e01f3f8d8b6b7158d01fdd870799ff3f402b676e358fcd879e7eb \
--hash=sha256:10095160dbe6bba8059ad6677a01da251431f4c68041bf796dcac0956b34f8f7 \
--hash=sha256:1a485117f97312bef45f5d79d2ff97eff4da503b8a04f3691f59d31141686459 \
--hash=sha256:1cef44ea4973344baed3d50a5da4a8843de3a6af7dea7fadf0a594e53ce5892f \
--hash=sha256:1dc2f46c31ef22b0aaa28cd71be897bea271e700636658d573df9c43c49ebbd0 \
--hash=sha256:21678d7e068707e4d54bdfeb8c250ebc548b51e499aed778b22112ca31a79669 \
--hash=sha256:278aa9d7cb56435c96d19f5d702e026bcf69f824e24b41e9b52706abd3565837 \
--hash=sha256:2ab011e3556a9a1d9461bd686870c527327765ed02fe53550531d6609a8a33ff \
--hash=sha256:2d90414e3b4b44b39825049185959488e084ea7fcaf6124afd5c00893938b09d \
--hash=sha256:2e506ecf89b6b9d304362ccef770831ec242a52c89dab1b4aabf1ab0eb1d5ed6 \
--hash=sha256:33cd9084fefc74cbacf88c92fd260b61211e00bcde38d640c369e5dc34a2b4e1 \
--hash=sha256:3b74467564814fbce322427a5664e6bcc7dae6dbc8acbef76300fe43ca4072ab \
--hash=sha256:3f3f4240d99d55eb97cb012e9adf401f5ed9cd827af0341ac44603832202b0d2 \
--hash=sha256:3fe1aea596f9539fc20cd9e52f098c842afc090168824fd4ca9744fe13151a03 \
--hash=sha256:4a8cb3c8637006c5bd8237ebb5992a76ba06e39988ad5cff2096227443e8fd6a \
--hash=sha256:4ef4ab8352861b99bd7fedb1fc6df3ea7f7d5216c789ba6d859e4ea06f1a4c45 \
--hash=sha256:5035bb997d163f346c22abcec75190e7e756a5349e7c708bd3d5fd7066a9a854 \
--hash=sha256:593a0f6fb0e186c5ba65465ed6f6215a30d1efa898c25e74de1c8577a1bff6d0 \
--hash=sha256:59cdcd934385f36e8bd76aedc234371cc75c848d95bdce804ac8aa8744cfeffa \
--hash=sha256:5a9b1320d8363a42d857fae8065a2174d38217cdd58cd8dc4f48d54e0591271e \
--hash=sha256:5f9681ec4c60d0da590552427d770636d9079038c30b265f507ccde23caa7823 \
--hash=sha256:5fd797a4837ba10671954e7c09010cec7aca67e09d193f4920a16beea5f66f65 \
--hash=sha256:6019e3480d933d3698f2ecb4b46d64bfadd64e718f04fac36e681f3254b49a93 \
--hash=sha256:603607f56a0ee84d9cd2c7e9b1d29b18a70684b94ee34f07b9ffe8dc9c8a9f81 \
--hash=sha256:60a4b481978ea2aad8fe8af1ecc271624d01b3cf4b09e9b643dd2fe19c07634c \
--hash=sha256:6b9812638d7aa8ecda2e8e1513fb4da999249603bffab7439a5f8f0bb362b0db \
--hash=sha256:6c7ae6e0778ab9610f5e80e0595957d101ab8de18c32a8c053a19943ef4831d0 \
--hash=sha256:6f83be8257b2f2dd6dea5ee62cd28db90584da7a7af1fba77a2102fc7943638a \
--hash=sha256:701e81e047f5c0cffd4ac828efca68b0bd270c616654966a051e9a5f836b385e \
--hash=sha256:703fd69d9cb21d6ec2086789df9be2cf8140a76ff127050c24007ea8940dcd3b \
--hash=sha256:7471d4486f23518cff343f1eec6c68d1b977ed74c3e6cc3e1ac896b9b7d68645 \
--hash=sha256:765d46f3d5e7a1d48075035e2d1a9164f683e3fccde834ca04602e6c588835bc \
--hash=sha256:7a09d203983104918c62f2eef9406f24c355511f9217967df23e70fa7f5b54ff \
--hash=sha256:7c20cc83b0df47129ec6ed8a47fa7dcfc309c5bad029464004162738502568bb \
--hash=sha256:7d7cfac2547c93389fa303fc0c0eb6698825564e8389c41c9b60009c746207b6 \
--hash=sha256:7d87c817b292efb748f1974f37e8bb8a8772ef92f05f84e507159360814bcc3f \
--hash=sha256:8141f654432cf75144d6103bfac2286b8adf23467201590b173a74535d6be22d \
--hash=sha256:849f2ff40264152f25589cb48ddb4a43d14db811f841ec73989bfc0c8c4853fa \
--hash=sha256:880c84ce59f49776cf120f77e7ca04877c97c6887917078dbc369eb47004d7cf \
--hash=sha256:94874584b733a18b310b0e954d53168e62cd4a0fd9db85b1903f0902a7eb33e8 \
--hash=sha256:95603eff711b8f3b9596e1c961dbeb745a792ba1904141612f194e07edd71e5f \
--hash=sha256:9585892091ae86045135d6a6129a644142d6a51b23e1428bb5de6d10bc0ce0c7 \
--hash=sha256:977bf5be704a88d46bf5b228df8b44521b1f3119d741062191608b3a6a38f224 \
--hash=sha256:9cdc46859024501c20ab74ad542cdf2f08b94b5ce384f2f569483fa3ed926d04 \
--hash=sha256:a34a5f034b339f69ef7f6a134c22d04b92e07b6ddc1dd65382e7e4ec65d6437d \
--hash=sha256:a655f7b755cfc5c07f2116b6dcf0ba148c89adef9a6d40c1b0f1fada878c4345 \
--hash=sha256:a7d12f2d2df195c8c4e49d2cdbad640353a856c62ca2c624d8b47aa33b65a2a2 \
--hash=sha256:abfe83e082c9208891e2158c1b5044a650ecec408b823bf6bf16cd7f8085cafa \
--hash=sha256:b25077a971c7da47bd6846a912a747f6963776d90720c88603b1b55d81790780 \
--hash=sha256:bf416a93e1331820c77e3429df26946dbd4fe105e9b487cd2d1b7298b75784a8 \
--hash=sha256:c04ae27e076d81a3839047d8eed57c1e17e361640616fd520d752375e3ba8f0c \
--hash=sha256:d5bea13c73f36c4346808df3fa806596163a7962b6d28001ca2a391cab856089 \
--hash=sha256:d75bef34e69e7effb7b4849e3f830e3174d2cc6ec7273503fdde111c222dc9b3 \
--hash=sha256:d93940664a5ccfd79f72dcb939b0c31a3479889f14f0eb95ec52976f8c0cae7d \
--hash=sha256:d9c89c521dc90c7564358e525f849b93ad1d710553c1491f66b8cce8113bc901 \
--hash=sha256:e0b36257dc90194784531c3b922d8d31fb2b4d8e5adfd27aff4eee7174176365 \
--hash=sha256:e1135264bcd40965cd35b0869e36952f54825024befdc7a923df9a7d83cfd800 \
--hash=sha256:e510d288e613d6927796dfb728e13e4530fc83b9ccac5888a21f7860486eab21 \
--hash=sha256:ee9a2c9a4b2421e77f8fe33ed0621dea03c66c710707553020b1e32f3afb6240 \
--hash=sha256:f19f11055ba2961eb39bdb1ff15763a53fca4fa0b5b624da3c7a528e83cdd09c \
--hash=sha256:f26544bc10c83a2ff9aa2e093500c1b473f327faae31fb468d591e5823333376 \
--hash=sha256:f4875cafc9a6482c04c7df52a725d1c41beb74913c0ff4ec8f189f1954a2afe9 \
--hash=sha256:f5179088ef6487c475604b7898731a6ddeeada7702cfb2162155b016703a8475 \
--hash=sha256:f63d1ae1ca17bb2c847e298c7bcf084a73d56d434b4c50509fb93a4b4300b0b2 \
--hash=sha256:ff4928dc1e9704b567171c16787238201fdbf023665573c12c02146fe1e02eec
# via -r requirements-base.in

7
requirements-base.in Normal file
View File

@ -0,0 +1,7 @@
psutil==5.9.3
ujson==5.5.0
ordered-set==4.1.0
result==0.8.0
# These two are also by Kevin
filenuke==0.0.0
onionrblocks==7.0.0

View File

@ -1 +0,0 @@
simplenotifications==0.2.18

View File

@ -1,8 +0,0 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --generate-hashes --output-file=requirements-notifications.txt requirements-notifications.in
#
simplenotifications==0.2.18 \
--hash=sha256:b7efd3d834b1922a3279287913d87fe4ef6fad181ca7edf54bfb8f1d973941e0

View File

@ -0,0 +1,445 @@
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile --generate-hashes --output-file=requirements-x86-all-plugins.txt requirements-base.in static-data/official-plugins/rpc/requirements.in static-data/official-plugins/tor/requirements.in static-data/official-plugins/wot/requirements.in
#
autocommand==2.2.1 \
--hash=sha256:85d03044c2a1fc1c7844ac41545045927aecde0cbaf8ea28b88e0cd8588ce5d3 \
--hash=sha256:fed420e9d02745821a782971b583c6970259ee0b229be2a0a401e1467a4f170f
# via jaraco-text
cffi==1.15.1 \
--hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \
--hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \
--hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \
--hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \
--hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \
--hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \
--hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \
--hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \
--hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \
--hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \
--hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \
--hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \
--hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \
--hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \
--hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \
--hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \
--hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \
--hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \
--hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \
--hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \
--hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \
--hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \
--hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \
--hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \
--hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \
--hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \
--hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \
--hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \
--hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \
--hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \
--hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \
--hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \
--hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \
--hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \
--hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \
--hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \
--hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \
--hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \
--hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \
--hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \
--hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \
--hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \
--hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \
--hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \
--hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \
--hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \
--hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \
--hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \
--hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \
--hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \
--hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \
--hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \
--hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \
--hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \
--hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \
--hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \
--hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \
--hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \
--hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \
--hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \
--hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \
--hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \
--hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \
--hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0
# via
# -r static-data/official-plugins/wot/requirements.in
# cryptography
# pynacl
cheroot==8.6.0 \
--hash=sha256:366adf6e7cac9555486c2d1be6297993022eff6f8c4655c1443268cca3f08e25 \
--hash=sha256:62cbced16f07e8aaf512673987cd6b1fc5ad00073345e9ed6c4e2a5cc2a3a22d
# via cherrypy
cherrypy==18.8.0 \
--hash=sha256:9b48cfba8a2f16d5b6419cc657e6d51db005ba35c5e3824e4728bb03bbc7ef9b \
--hash=sha256:b56097025dc78a76a59db551b3a82871c6b3a0107b80b12ff759e4c0b3b947ce
# via -r static-data/official-plugins/rpc/requirements.in
cryptography==38.0.1 \
--hash=sha256:0297ffc478bdd237f5ca3a7dc96fc0d315670bfa099c04dc3a4a2172008a405a \
--hash=sha256:10d1f29d6292fc95acb597bacefd5b9e812099d75a6469004fd38ba5471a977f \
--hash=sha256:16fa61e7481f4b77ef53991075de29fc5bacb582a1244046d2e8b4bb72ef66d0 \
--hash=sha256:194044c6b89a2f9f169df475cc167f6157eb9151cc69af8a2a163481d45cc407 \
--hash=sha256:1db3d807a14931fa317f96435695d9ec386be7b84b618cc61cfa5d08b0ae33d7 \
--hash=sha256:3261725c0ef84e7592597606f6583385fed2a5ec3909f43bc475ade9729a41d6 \
--hash=sha256:3b72c360427889b40f36dc214630e688c2fe03e16c162ef0aa41da7ab1455153 \
--hash=sha256:3e3a2599e640927089f932295a9a247fc40a5bdf69b0484532f530471a382750 \
--hash=sha256:3fc26e22840b77326a764ceb5f02ca2d342305fba08f002a8c1f139540cdfaad \
--hash=sha256:5067ee7f2bce36b11d0e334abcd1ccf8c541fc0bbdaf57cdd511fdee53e879b6 \
--hash=sha256:52e7bee800ec869b4031093875279f1ff2ed12c1e2f74923e8f49c916afd1d3b \
--hash=sha256:64760ba5331e3f1794d0bcaabc0d0c39e8c60bf67d09c93dc0e54189dfd7cfe5 \
--hash=sha256:765fa194a0f3372d83005ab83ab35d7c5526c4e22951e46059b8ac678b44fa5a \
--hash=sha256:79473cf8a5cbc471979bd9378c9f425384980fcf2ab6534b18ed7d0d9843987d \
--hash=sha256:896dd3a66959d3a5ddcfc140a53391f69ff1e8f25d93f0e2e7830c6de90ceb9d \
--hash=sha256:89ed49784ba88c221756ff4d4755dbc03b3c8d2c5103f6d6b4f83a0fb1e85294 \
--hash=sha256:ac7e48f7e7261207d750fa7e55eac2d45f720027d5703cd9007e9b37bbb59ac0 \
--hash=sha256:ad7353f6ddf285aeadfaf79e5a6829110106ff8189391704c1d8801aa0bae45a \
--hash=sha256:b0163a849b6f315bf52815e238bc2b2346604413fa7c1601eea84bcddb5fb9ac \
--hash=sha256:b6c9b706316d7b5a137c35e14f4103e2115b088c412140fdbd5f87c73284df61 \
--hash=sha256:c2e5856248a416767322c8668ef1845ad46ee62629266f84a8f007a317141013 \
--hash=sha256:ca9f6784ea96b55ff41708b92c3f6aeaebde4c560308e5fbbd3173fbc466e94e \
--hash=sha256:d1a5bd52d684e49a36582193e0b89ff267704cd4025abefb9e26803adeb3e5fb \
--hash=sha256:d3971e2749a723e9084dd507584e2a2761f78ad2c638aa31e80bc7a15c9db4f9 \
--hash=sha256:d4ef6cc305394ed669d4d9eebf10d3a101059bdcf2669c366ec1d14e4fb227bd \
--hash=sha256:d9e69ae01f99abe6ad646947bba8941e896cb3aa805be2597a0400e0764b5818
# via secretstorage
filenuke==0.0.0 \
--hash=sha256:147011c0125121469cae0a8a7f4df399f470e54aa29a08f2d2c099bf0118dcee \
--hash=sha256:c55535dcecfdb27c5f4ce664d46e115950b5429763b5db75c198053646177f8f
# via -r requirements-base.in
inflect==6.0.0 \
--hash=sha256:0bc1516ec2725e2d8221707a612245093cb6f1cea209cfd8cbd4fc5e96fa6365 \
--hash=sha256:e3b85d65a296843268f35f4136283ad7c012a129375db1529d49b4b01ecb400b
# via jaraco-text
jaraco-classes==3.2.2 \
--hash=sha256:6745f113b0b588239ceb49532aa09c3ebb947433ce311ef2f8e3ad64ebb74594 \
--hash=sha256:e6ef6fd3fcf4579a7a019d87d1e56a883f4e4c35cfe925f86731abc58804e647
# via
# jaraco-collections
# keyring
jaraco-collections==3.5.2 \
--hash=sha256:072b93eb35f9e48508485755534e66a34ef1cc84af291fd27f39b44d4c0dd2c3 \
--hash=sha256:1ca12fa4b7067dfc8d7f791c1a8660d970a2bf2f80536ba0aa5cbb71fe1261f1
# via cherrypy
jaraco-context==4.1.2 \
--hash=sha256:9327d3e6901923e5a7097aa2df4b9c2bc13f845c7672692e3827ebd1b3d67606 \
--hash=sha256:a58e94dd67871639abc091b57d32842449b230777570ef2bcec3dc16b912613e
# via jaraco-text
jaraco-functools==3.5.1 \
--hash=sha256:c8774f73323de42250a659934215da1d899b02c66a6133f1cb79f02a5aff4f38 \
--hash=sha256:d0adcf91710a0853efe9f23a78fad586bf67df572f0d6d8e0fa36d289ae1c1d9
# via
# cheroot
# jaraco-text
# tempora
jaraco-text==3.9.1 \
--hash=sha256:3ca615c4135e151d21206075ec4aface8a2fbc3e68437fe709a6541428a635f9 \
--hash=sha256:d57cd4448a588020318425e04194e897f96fc23b92b82ff9308a24d5cbf2b3fb
# via jaraco-collections
jeepney==0.8.0 \
--hash=sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806 \
--hash=sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755
# via
# keyring
# secretstorage
json-rpc==1.13.0 \
--hash=sha256:84b45058e5ba95f49c7b6afcf7e03ab86bee89bf2c01f3ad8dd41fe114fc1f84 \
--hash=sha256:def0dbcf5b7084fc31d677f2f5990d988d06497f2f47f13024274cfb2d5d7589
# via -r static-data/official-plugins/rpc/requirements.in
kasten==3.0.0 \
--hash=sha256:52894af46d6e1339f0d5fa8961892b292f99176848bce11877fe4a435b6782e5 \
--hash=sha256:b22ebdc5f475c2ef9ab74abc36552add0b37732a7ce2be6bd7977ee41b2163b4
# via onionrblocks
keyring==23.9.3 \
--hash=sha256:69732a15cb1433bdfbc3b980a8a36a04878a6cfd7cb99f497b573f31618001c0 \
--hash=sha256:69b01dd83c42f590250fe7a1f503fc229b14de83857314b1933a3ddbf595c4a5
# via -r static-data/official-plugins/wot/requirements.in
mimcvdf==1.2.1 \
--hash=sha256:7c837c46cfb9dce4ba895bc706a69646d4d5185c66aeaa333b5cfaa9a7d06dc4
# via kasten
more-itertools==8.14.0 \
--hash=sha256:1bc4f91ee5b1b31ac7ceacc17c09befe6a40a503907baf9c839c229b5095cfd2 \
--hash=sha256:c09443cd3d5438b8dafccd867a6bc1cb0894389e90cb53d227456b0b0bccb750
# via
# cheroot
# cherrypy
# jaraco-classes
# jaraco-functools
# jaraco-text
msgpack==1.0.4 \
--hash=sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467 \
--hash=sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae \
--hash=sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92 \
--hash=sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef \
--hash=sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624 \
--hash=sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227 \
--hash=sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88 \
--hash=sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9 \
--hash=sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8 \
--hash=sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd \
--hash=sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6 \
--hash=sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55 \
--hash=sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e \
--hash=sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2 \
--hash=sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44 \
--hash=sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6 \
--hash=sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9 \
--hash=sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab \
--hash=sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae \
--hash=sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa \
--hash=sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9 \
--hash=sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e \
--hash=sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250 \
--hash=sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce \
--hash=sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075 \
--hash=sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236 \
--hash=sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae \
--hash=sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e \
--hash=sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f \
--hash=sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08 \
--hash=sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6 \
--hash=sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d \
--hash=sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43 \
--hash=sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1 \
--hash=sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6 \
--hash=sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0 \
--hash=sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c \
--hash=sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff \
--hash=sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db \
--hash=sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243 \
--hash=sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661 \
--hash=sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba \
--hash=sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e \
--hash=sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb \
--hash=sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52 \
--hash=sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6 \
--hash=sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1 \
--hash=sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f \
--hash=sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da \
--hash=sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f \
--hash=sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c \
--hash=sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8
# via kasten
onionrblocks==7.0.0 \
--hash=sha256:53e90964371076d9daf2ed0790b21f174ef3321f4f1808209cc6dd9b7ff6d8ff \
--hash=sha256:54af28d0be856209525646c4ef9f977f95f0ae1329b2cc023b351317c9d0eef7
# via -r requirements-base.in
ordered-set==4.1.0 \
--hash=sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562 \
--hash=sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8
# via -r requirements-base.in
portend==3.1.0 \
--hash=sha256:239e3116045ea823f6df87d6168107ad75ccc0590e37242af0cc1e98c5d224e4 \
--hash=sha256:9e735cee3a5c1961f09e3f3ba6dc498198c2d70b473d98d0d1504b8d1e7a3d61
# via cherrypy
psutil==5.9.3 \
--hash=sha256:07d880053c6461c9b89cd5d4808f3b8336665fa3acdefd6777662c5ed73a851a \
--hash=sha256:12500d761ac091f2426567f19f95fd3f15a197d96befb44a5c1e3cbe6db5752c \
--hash=sha256:1b540599481c73408f6b392cdffef5b01e8ff7a2ac8caae0a91b8222e88e8f1e \
--hash=sha256:35feafe232d1aaf35d51bd42790cbccb882456f9f18cdc411532902370d660df \
--hash=sha256:3a7826e68b0cf4ce2c1ee385d64eab7d70e3133171376cac53d7c1790357ec8f \
--hash=sha256:46907fa62acaac364fff0b8a9da7b360265d217e4fdeaca0a2397a6883dffba2 \
--hash=sha256:4bd4854f0c83aa84a5a40d3b5d0eb1f3c128f4146371e03baed4589fe4f3c931 \
--hash=sha256:538fcf6ae856b5e12d13d7da25ad67f02113c96f5989e6ad44422cb5994ca7fc \
--hash=sha256:547ebb02031fdada635452250ff39942db8310b5c4a8102dfe9384ee5791e650 \
--hash=sha256:5e8b50241dd3c2ed498507f87a6602825073c07f3b7e9560c58411c14fe1e1c9 \
--hash=sha256:5fa88e3d5d0b480602553d362c4b33a63e0c40bfea7312a7bf78799e01e0810b \
--hash=sha256:68fa227c32240c52982cb931801c5707a7f96dd8927f9102d6c7771ea1ff5698 \
--hash=sha256:6ced1ad823ecfa7d3ce26fe8aa4996e2e53fb49b7fed8ad81c80958501ec0619 \
--hash=sha256:71b1206e7909792d16933a0d2c1c7f04ae196186c51ba8567abae1d041f06dcb \
--hash=sha256:767ef4fa33acda16703725c0473a91e1832d296c37c63896c7153ba81698f1ab \
--hash=sha256:7ccfcdfea4fc4b0a02ca2c31de7fcd186beb9cff8207800e14ab66f79c773af6 \
--hash=sha256:7e4939ff75149b67aef77980409f156f0082fa36accc475d45c705bb00c6c16a \
--hash=sha256:828c9dc9478b34ab96be75c81942d8df0c2bb49edbb481f597314d92b6441d89 \
--hash=sha256:8a4e07611997acf178ad13b842377e3d8e9d0a5bac43ece9bfc22a96735d9a4f \
--hash=sha256:941a6c2c591da455d760121b44097781bc970be40e0e43081b9139da485ad5b7 \
--hash=sha256:9a4af6ed1094f867834f5f07acd1250605a0874169a5fcadbcec864aec2496a6 \
--hash=sha256:9ec296f565191f89c48f33d9544d8d82b0d2af7dd7d2d4e6319f27a818f8d1cc \
--hash=sha256:9ec95df684583b5596c82bb380c53a603bb051cf019d5c849c47e117c5064395 \
--hash=sha256:a04a1836894c8279e5e0a0127c0db8e198ca133d28be8a2a72b4db16f6cf99c1 \
--hash=sha256:a3d81165b8474087bb90ec4f333a638ccfd1d69d34a9b4a1a7eaac06648f9fbe \
--hash=sha256:b4a247cd3feaae39bb6085fcebf35b3b8ecd9b022db796d89c8f05067ca28e71 \
--hash=sha256:ba38cf9984d5462b506e239cf4bc24e84ead4b1d71a3be35e66dad0d13ded7c1 \
--hash=sha256:beb57d8a1ca0ae0eb3d08ccaceb77e1a6d93606f0e1754f0d60a6ebd5c288837 \
--hash=sha256:d266cd05bd4a95ca1c2b9b5aac50d249cf7c94a542f47e0b22928ddf8b80d1ef \
--hash=sha256:d8c3cc6bb76492133474e130a12351a325336c01c96a24aae731abf5a47fe088 \
--hash=sha256:db8e62016add2235cc87fb7ea000ede9e4ca0aa1f221b40cef049d02d5d2593d \
--hash=sha256:e7507f6c7b0262d3e7b0eeda15045bf5881f4ada70473b87bc7b7c93b992a7d7 \
--hash=sha256:ed15edb14f52925869250b1375f0ff58ca5c4fa8adefe4883cfb0737d32f5c02 \
--hash=sha256:f57d63a2b5beaf797b87024d018772439f9d3103a395627b77d17a8d72009543 \
--hash=sha256:fa5e32c7d9b60b2528108ade2929b115167fe98d59f89555574715054f50fa31 \
--hash=sha256:fe79b4ad4836e3da6c4650cb85a663b3a51aef22e1a829c384e18fae87e5e727
# via -r requirements-base.in
pycparser==2.21 \
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
# via cffi
pydantic==1.10.2 \
--hash=sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42 \
--hash=sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624 \
--hash=sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e \
--hash=sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559 \
--hash=sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709 \
--hash=sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9 \
--hash=sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d \
--hash=sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52 \
--hash=sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda \
--hash=sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912 \
--hash=sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c \
--hash=sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525 \
--hash=sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe \
--hash=sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41 \
--hash=sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b \
--hash=sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283 \
--hash=sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965 \
--hash=sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c \
--hash=sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410 \
--hash=sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5 \
--hash=sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116 \
--hash=sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98 \
--hash=sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f \
--hash=sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644 \
--hash=sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13 \
--hash=sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd \
--hash=sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254 \
--hash=sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6 \
--hash=sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488 \
--hash=sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5 \
--hash=sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c \
--hash=sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1 \
--hash=sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a \
--hash=sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2 \
--hash=sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d \
--hash=sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236
# via inflect
pynacl==1.5.0 \
--hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \
--hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \
--hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \
--hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \
--hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \
--hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \
--hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \
--hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \
--hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \
--hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543
# via
# -r static-data/official-plugins/wot/requirements.in
# onionrblocks
pysocks==1.7.1 \
--hash=sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
# via -r static-data/official-plugins/tor/requirements.in
pytz==2022.2.1 \
--hash=sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197 \
--hash=sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5
# via tempora
result==0.8.0 \
--hash=sha256:c48c909e92181a075ba358228a3fe161e26d205dad416ad81f27f23515a5626d \
--hash=sha256:d6a6258f32c057a4e0478999c6ce43dcadaf8ea435f58ac601ae2768f93ef243
# via -r requirements-base.in
secretstorage==3.3.3 \
--hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \
--hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99
# via keyring
six==1.16.0 \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
# via cheroot
stem==1.8.1 \
--hash=sha256:81d43a7c668ba9d7bc1103b2e7a911e9d148294b373d27a59ae8da79ef7a3e2f
# via -r static-data/official-plugins/tor/requirements.in
tempora==5.0.2 \
--hash=sha256:31fa5bb33b2641026211f23e808eb8bd351901988b167d45f323c8f450ecf211 \
--hash=sha256:e65d32ae68ad772ee738d802689f689b3f883e165e8dadd39aa89ef317b12b99
# via portend
typing-extensions==4.3.0 \
--hash=sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02 \
--hash=sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6
# via pydantic
ujson==5.5.0 \
--hash=sha256:0762a4fdf86e01f3f8d8b6b7158d01fdd870799ff3f402b676e358fcd879e7eb \
--hash=sha256:10095160dbe6bba8059ad6677a01da251431f4c68041bf796dcac0956b34f8f7 \
--hash=sha256:1a485117f97312bef45f5d79d2ff97eff4da503b8a04f3691f59d31141686459 \
--hash=sha256:1cef44ea4973344baed3d50a5da4a8843de3a6af7dea7fadf0a594e53ce5892f \
--hash=sha256:1dc2f46c31ef22b0aaa28cd71be897bea271e700636658d573df9c43c49ebbd0 \
--hash=sha256:21678d7e068707e4d54bdfeb8c250ebc548b51e499aed778b22112ca31a79669 \
--hash=sha256:278aa9d7cb56435c96d19f5d702e026bcf69f824e24b41e9b52706abd3565837 \
--hash=sha256:2ab011e3556a9a1d9461bd686870c527327765ed02fe53550531d6609a8a33ff \
--hash=sha256:2d90414e3b4b44b39825049185959488e084ea7fcaf6124afd5c00893938b09d \
--hash=sha256:2e506ecf89b6b9d304362ccef770831ec242a52c89dab1b4aabf1ab0eb1d5ed6 \
--hash=sha256:33cd9084fefc74cbacf88c92fd260b61211e00bcde38d640c369e5dc34a2b4e1 \
--hash=sha256:3b74467564814fbce322427a5664e6bcc7dae6dbc8acbef76300fe43ca4072ab \
--hash=sha256:3f3f4240d99d55eb97cb012e9adf401f5ed9cd827af0341ac44603832202b0d2 \
--hash=sha256:3fe1aea596f9539fc20cd9e52f098c842afc090168824fd4ca9744fe13151a03 \
--hash=sha256:4a8cb3c8637006c5bd8237ebb5992a76ba06e39988ad5cff2096227443e8fd6a \
--hash=sha256:4ef4ab8352861b99bd7fedb1fc6df3ea7f7d5216c789ba6d859e4ea06f1a4c45 \
--hash=sha256:5035bb997d163f346c22abcec75190e7e756a5349e7c708bd3d5fd7066a9a854 \
--hash=sha256:593a0f6fb0e186c5ba65465ed6f6215a30d1efa898c25e74de1c8577a1bff6d0 \
--hash=sha256:59cdcd934385f36e8bd76aedc234371cc75c848d95bdce804ac8aa8744cfeffa \
--hash=sha256:5a9b1320d8363a42d857fae8065a2174d38217cdd58cd8dc4f48d54e0591271e \
--hash=sha256:5f9681ec4c60d0da590552427d770636d9079038c30b265f507ccde23caa7823 \
--hash=sha256:5fd797a4837ba10671954e7c09010cec7aca67e09d193f4920a16beea5f66f65 \
--hash=sha256:6019e3480d933d3698f2ecb4b46d64bfadd64e718f04fac36e681f3254b49a93 \
--hash=sha256:603607f56a0ee84d9cd2c7e9b1d29b18a70684b94ee34f07b9ffe8dc9c8a9f81 \
--hash=sha256:60a4b481978ea2aad8fe8af1ecc271624d01b3cf4b09e9b643dd2fe19c07634c \
--hash=sha256:6b9812638d7aa8ecda2e8e1513fb4da999249603bffab7439a5f8f0bb362b0db \
--hash=sha256:6c7ae6e0778ab9610f5e80e0595957d101ab8de18c32a8c053a19943ef4831d0 \
--hash=sha256:6f83be8257b2f2dd6dea5ee62cd28db90584da7a7af1fba77a2102fc7943638a \
--hash=sha256:701e81e047f5c0cffd4ac828efca68b0bd270c616654966a051e9a5f836b385e \
--hash=sha256:703fd69d9cb21d6ec2086789df9be2cf8140a76ff127050c24007ea8940dcd3b \
--hash=sha256:7471d4486f23518cff343f1eec6c68d1b977ed74c3e6cc3e1ac896b9b7d68645 \
--hash=sha256:765d46f3d5e7a1d48075035e2d1a9164f683e3fccde834ca04602e6c588835bc \
--hash=sha256:7a09d203983104918c62f2eef9406f24c355511f9217967df23e70fa7f5b54ff \
--hash=sha256:7c20cc83b0df47129ec6ed8a47fa7dcfc309c5bad029464004162738502568bb \
--hash=sha256:7d7cfac2547c93389fa303fc0c0eb6698825564e8389c41c9b60009c746207b6 \
--hash=sha256:7d87c817b292efb748f1974f37e8bb8a8772ef92f05f84e507159360814bcc3f \
--hash=sha256:8141f654432cf75144d6103bfac2286b8adf23467201590b173a74535d6be22d \
--hash=sha256:849f2ff40264152f25589cb48ddb4a43d14db811f841ec73989bfc0c8c4853fa \
--hash=sha256:880c84ce59f49776cf120f77e7ca04877c97c6887917078dbc369eb47004d7cf \
--hash=sha256:94874584b733a18b310b0e954d53168e62cd4a0fd9db85b1903f0902a7eb33e8 \
--hash=sha256:95603eff711b8f3b9596e1c961dbeb745a792ba1904141612f194e07edd71e5f \
--hash=sha256:9585892091ae86045135d6a6129a644142d6a51b23e1428bb5de6d10bc0ce0c7 \
--hash=sha256:977bf5be704a88d46bf5b228df8b44521b1f3119d741062191608b3a6a38f224 \
--hash=sha256:9cdc46859024501c20ab74ad542cdf2f08b94b5ce384f2f569483fa3ed926d04 \
--hash=sha256:a34a5f034b339f69ef7f6a134c22d04b92e07b6ddc1dd65382e7e4ec65d6437d \
--hash=sha256:a655f7b755cfc5c07f2116b6dcf0ba148c89adef9a6d40c1b0f1fada878c4345 \
--hash=sha256:a7d12f2d2df195c8c4e49d2cdbad640353a856c62ca2c624d8b47aa33b65a2a2 \
--hash=sha256:abfe83e082c9208891e2158c1b5044a650ecec408b823bf6bf16cd7f8085cafa \
--hash=sha256:b25077a971c7da47bd6846a912a747f6963776d90720c88603b1b55d81790780 \
--hash=sha256:bf416a93e1331820c77e3429df26946dbd4fe105e9b487cd2d1b7298b75784a8 \
--hash=sha256:c04ae27e076d81a3839047d8eed57c1e17e361640616fd520d752375e3ba8f0c \
--hash=sha256:d5bea13c73f36c4346808df3fa806596163a7962b6d28001ca2a391cab856089 \
--hash=sha256:d75bef34e69e7effb7b4849e3f830e3174d2cc6ec7273503fdde111c222dc9b3 \
--hash=sha256:d93940664a5ccfd79f72dcb939b0c31a3479889f14f0eb95ec52976f8c0cae7d \
--hash=sha256:d9c89c521dc90c7564358e525f849b93ad1d710553c1491f66b8cce8113bc901 \
--hash=sha256:e0b36257dc90194784531c3b922d8d31fb2b4d8e5adfd27aff4eee7174176365 \
--hash=sha256:e1135264bcd40965cd35b0869e36952f54825024befdc7a923df9a7d83cfd800 \
--hash=sha256:e510d288e613d6927796dfb728e13e4530fc83b9ccac5888a21f7860486eab21 \
--hash=sha256:ee9a2c9a4b2421e77f8fe33ed0621dea03c66c710707553020b1e32f3afb6240 \
--hash=sha256:f19f11055ba2961eb39bdb1ff15763a53fca4fa0b5b624da3c7a528e83cdd09c \
--hash=sha256:f26544bc10c83a2ff9aa2e093500c1b473f327faae31fb468d591e5823333376 \
--hash=sha256:f4875cafc9a6482c04c7df52a725d1c41beb74913c0ff4ec8f189f1954a2afe9 \
--hash=sha256:f5179088ef6487c475604b7898731a6ddeeada7702cfb2162155b016703a8475 \
--hash=sha256:f63d1ae1ca17bb2c847e298c7bcf084a73d56d434b4c50509fb93a4b4300b0b2 \
--hash=sha256:ff4928dc1e9704b567171c16787238201fdbf023665573c12c02146fe1e02eec
# via -r requirements-base.in
zc-lockfile==2.0 \
--hash=sha256:307ad78227e48be260e64896ec8886edc7eae22d8ec53e4d528ab5537a83203b \
--hash=sha256:cc33599b549f0c8a248cb72f3bf32d77712de1ff7ee8814312eb6456b42c015f
# via cherrypy
# WARNING: The following packages were not pinned, but pip requires them to be
# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
# setuptools

View File

@ -1,40 +0,0 @@
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile
#
cffi==1.15.1
# via
# -r requirements.in
# pynacl
filenuke==0.0.0
# via -r requirements.in
kasten==3.0.0
# via onionrblocks
mimcvdf==1.2.1
# via kasten
msgpack==1.0.3
# via kasten
niceware==0.2.1
# via -r requirements.in
onionrblocks==7.0.0
# via -r requirements.in
ordered-set==4.1.0
# via -r requirements.in
psutil==5.9.1
# via -r requirements.in
pycparser==2.19
# via cffi
pynacl==1.5.0
# via
# -r requirements.in
# onionrblocks
pysocks==1.7.1
# via -r requirements.in
stem==1.8.0
# via -r requirements.in
ujson==5.4.0
# via -r requirements.in
unpaddedbase32==0.2.0
# via -r requirements.in

View File

@ -1,150 +0,0 @@
#!/usr/bin/env python3
import argparse
import os
from threading import Thread
from time import sleep
from subprocess import DEVNULL
import ujson
from psutil import Popen
from psutil import Process
import sys
script_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(script_dir + '/src/')
import onionrvalues
sub_script = script_dir + '/' + onionrvalues.SCRIPT_NAME
parser = argparse.ArgumentParser()
parser.add_argument(
"--bind-address", help="Address to bind to. Be very careful with non-loopback",
type=str, default="")
parser.add_argument(
"--port", help="Port to bind to, must be available and possible",
type=int, default=0)
parser.add_argument(
"--use-bootstrap-file", help="Use bootstrap node list file",
type=int, default=1)
parser.add_argument(
"--show-stats", help="Display curses output of Onionr stats",
type=int, default=0)
parser.add_argument(
"--onboarding", help="Use Onionr onboarding (if first load)",
type=int, default=1)
parser.add_argument(
"--security-level", help="Set Onionr security level",
type=int, default=0)
parser.add_argument(
'--open-ui', help='Open onionr web ui after started',
type=int, default=1)
parser.add_argument(
'--random-localhost-ip', help='bind to random localhost IP for extra security',
type=int, default=1)
parser.add_argument(
'--use-tor', help='Use Tor transport',
type=int, default=1)
parser.add_argument(
'--private-key', help='Use existing private key',
type=str, default=0)
parser.add_argument(
'--animated-background', help='Animated background on webui index. Just for looks.',
type=int, default=0)
parser.add_argument(
'--keep-log-on-exit', help='Onionr can keep or delete its log file on exit',
type=int, default=0)
parser.add_argument(
'--use-upload-mixing', help='Re-upload blocks uploaded to us. Slow but more secure',
type=int, default=0)
parser.add_argument(
'--dev-mode',
help='Developer mode makes restarting and testing Onionr less tedious during development',
type=int, default=0)
parser.add_argument(
'--disable-plugin-list',
help='plugins to disable by name, separate with commas',
type=str, default='chat'
)
parser.add_argument(
'--store-plaintext',
help='store plaintext blocks or not. note that encrypted blocks may not really be encrypted, but we cannot detect that',
type=int, default=1
)
args = parser.parse_args()
p = Popen([sub_script, 'version'])
p.wait()
print("Configuring Onionr before starting daemon")
from filepaths import config_file, keys_file
from coredb import blockmetadb
import onionrcrypto
with open(config_file, 'r') as cf:
config = ujson.loads(cf.read())
if args.private_key:
priv = args.private_key
pub = onionrcrypto.cryptoutils.get_pub_key_from_priv(priv)
with open(keys_file, "a") as f:
f.write(',' + pub.decode() + ',' + priv)
config['general']['public_key'] = pub
config['plugins']['disabled'] = args.disable_plugin_list.split(',')
config['general']['dev_mode'] = False
config['general']['store_plaintext_blocks'] = True
config['general']['use_bootstrap_list'] = True
config['transports']['tor'] = True
config['general']['bind_port'] = 0 # client api server port
config['general']['bind_address'] = '' # client api server address
if args.bind_address:
config['general']['bind_address'] = args.bind_address
if args.port:
config['client']['client']['port'] = args.port
if not args.use_bootstrap_file:
config['general']['use_bootstrap_list'] = False
if not args.store_plaintext:
config['general']['store_plaintext_blocks'] = False
if args.dev_mode:
config['general']['dev_mode'] = True
if not args.onboarding:
config['onboarding']['done'] = True
if not args.random_localhost_ip:
config['general']['random_bind_ip'] = False
if not args.use_tor:
config['transports']['tor'] = False
if not args.animated_background:
config['ui']['animated_background'] = False
if args.keep_log_on_exit:
config['log']['file']['remove_on_exit'] = True
else:
config['log']['file']['remove_on_exit'] = False
config['general']['upload_mixing'] = False
if args.use_upload_mixing:
config['general']['upload_mixing'] = True
config['general']['display_header'] = False
config['general']['security_level'] = args.security_level
with open(config_file, 'w') as cf:
cf.write(ujson.dumps(config, reject_bytes=False))
if args.open_ui:
p = Popen([sub_script, 'start'])
sleep(2)
Popen([sub_script, 'openhome'])
else:
p = Popen([sub_script, 'start'])
p.wait()

View File

@ -1,51 +0,0 @@
#!/bin/sh
set -x
ORIG_ONIONR_RUN_DIR=`pwd`
export ORIG_ONIONR_RUN_DIR
cd "$(dirname "$0")"
if [[ -n "$ONIONR_DOCKER" ]]; then
[[ -f "/privkey" ]] && privkey_opt="--private-key /privkey"
[[ -n "$ONIONR_ONBOARDING" ]] || ONIONR_ONBOARDING=0
[[ -n "$ONIONR_OPEN_UI" ]] || ONIONR_OPEN_UI=0
[[ -n "$ONIONR_RANDOM_LOCALHOST_IP" ]] || ONIONR_RANDOM_LOCALHOST_IP=0
[[ -n "$ONIONR_BIND_ADDRESS" ]] || ONIONR_BIND_ADDRESS=0.0.0.0
[[ -n "$ONIONR_PORT" ]] || ONIONR_PORT=8080
fi
[[ -n "$ONIONR_PRIVATE_KEY_FILE" ]] && privkey_opt="--private-key $ONIONR_PRIVATE_KEY_FILE"
[[ -n "$ONIONR_USE_BOOTSTRAP_FILE" ]] && bootstrap_opt="--use-bootstrap-file $ONIONR_USE_BOOTSTRAP_FILE"
[[ -n "$ONIONR_SHOW_STATS" ]] && show_stats_opt="--show-stats $ONIONR_SHOW_STATS"
[[ -n "$ONIONR_ONBOARDING" ]] && onboarding_opt="--onboarding $ONIONR_ONBOARDING"
[[ -n "$ONIONR_SECURITY_LEVEL" ]] && security_level_opt="--security-level $ONIONR_SECURITY_LEVEL"
[[ -n "$ONIONR_OPEN_UI" ]] && open_ui_opt="--open-ui $ONIONR_OPEN_UI"
[[ -n "$ONIONR_RANDOM_LOCALHOST_IP" ]] && random_localhost_ip_opt="--random-localhost-ip $ONIONR_RANDOM_LOCALHOST_IP"
[[ -n "$ONIONR_USE_TOR" ]] && use_tor_opt="--use-tor $ONIONR_USE_TOR"
[[ -n "$ONIONR_ANIMATED_BACKGROUND" ]] && animated_background_opt="--animated-background $ONIONR_ANIMATED_BACKGROUND"
[[ -n "$ONIONR_KEEP_LOG" ]] && keep_log_opt="--keep-log-on-exit $ONIONR_KEEP_LOG"
[[ -n "$ONIONR_USE_UPLOAD_MIXING" ]] && use_upload_mixing_opt="--use-upload-mixing $ONIONR_USE_UPLOAD_MIXING"
[[ -n "$ONIONR_DEV_MODE" ]] && dev_mode_opt="--dev-mode $ONIONR_DEV_MODE"
[[ -n "$ONIONR_DISABLE_PLUGIN_LIST" ]] && disable_plugin_list_opt=" --disable-plugin-list $ONIONR_DISABLE_PLUGIN_LIST"
[[ -n "$ONIONR_STORE_PLAINTEXT" ]] && store_plaintext_opt="--store-plaintext $ONIONR_STORE_PLAINTEXT"
[[ -n "$ONIONR_BIND_ADDRESS" ]] && bind_address_opt="--bind-address $ONIONR_BIND_ADDRESS"
[[ -n "$ONIONR_PORT" ]] && port_opt="--port $ONIONR_PORT"
python3 run-onionr-node.py \
$privkey_opt \
$bootstrap_opt \
$show_stats_opt \
$onboarding_opt \
$security_level_opt \
$open_ui_opt \
$random_localhost_ip_opt \
$use_tor_opt \
$animated_background_opt \
$keep_log_opt \
$use_upload_mixing_opt \
$dev_mode_opt \
$disable_plugin_list_opt \
$store_plaintext_opt \
$bind_address_opt \
$port_opt \
"$@"

View File

@ -1,33 +0,0 @@
#!/usr/bin/env python3
import os, sys
import tempfile, shutil
import stat
env_var = "firejailed-onionr"
def copytree(src, dst, symlinks=False, ignore=None):
for item in os.listdir(src):
if item in (".git", ".vscode", ".github"):
continue
s = os.path.join(src, item)
d = os.path.join(dst, item)
if os.path.isdir(s):
shutil.copytree(s, d, symlinks, ignore)
else:
shutil.copy2(s, d)
env_var = "firejailed-onionr"
directory = os.path.dirname(os.path.realpath(sys.argv[0]))
if not os.getenv(env_var):
temp_dir = tempfile.mkdtemp()
print(temp_dir)
copytree(directory, temp_dir)
os.system(f"firejail --env={env_var}={temp_dir} --private={temp_dir} python3 ./sandboxed-onionr.py")
sys.exit(0)
os.system(f"python3 -m pip install -r ./requirements.txt --user")
os.system(f"./onionr.sh start &")

View File

@ -1,7 +1 @@
This directory contains useful scripts and utilities that don't make sense to include as official Onionr features.
passphrase-generator.py: very simple utility to generate and print a strong passphrase to stdout. 256 bits of entropy by default.
enable-dev-config.py/disable-dev-config.py: enable/disable dev default config setup
block-spammer.py: attack tool for spamming blocks
announce-attack.py: flood a node with false nodes
run-unit-test-by-name: runs a unit test (no browser, runtime or intgegration test) by name

View File

@ -1,51 +0,0 @@
#!/usr/bin/env python3
"""Craft and send requests to the local client API"""
import sys
import os
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
import atexit
import readline
histfile = os.path.join(os.path.expanduser("~"), ".onionr_history")
try:
readline.read_history_file(histfile)
# default history len is -1 (infinite), which may grow unruly
readline.set_history_length(1000)
except FileNotFoundError:
pass
atexit.register(readline.write_history_file, histfile)
from onionrutils.localcommand import local_command
from onionrutils.localcommand import get_hostname
try:
print('API file found, probably running on ' + get_hostname())
except TypeError:
print('Onionr not running')
sys.exit(1)
print('1. get request (default)')
print('2. post request')
choice = input(">").lower().strip()
post = False
post_data = {}
json = False
endpoint = input("URL Endpoint: ")
data = input("Data url param: ")
if choice in ("2", "post", "post request"):
post = True
print("Enter post data")
post_data = input()
if post_data:
print("Is this JSON?")
json = input("y/n").lower().strip()
if json == "y":
json = True
ret = local_command(endpoint, data=data, post=post, post_data=post_data, is_json=json)
print("Response: \n", ret)

View File

@ -11,12 +11,9 @@ conf['tor']['existing_control_port'] = 0
conf['tor']['existing_control_password'] = ""
conf['tor']['existing_socks_port'] = 0
conf['general']['dev_mode'] = False
conf['general']['insert_deniable_blocks'] = True
conf['general']['random_bind_ip'] = True
conf['general']['display_header'] = True
conf['general']['security_level'] = 0
conf['general']['use_bootstrap_list'] = True
conf['onboarding']['done'] = False
conf['general']['minimum_block_pow'] = 5
conf['general']['minimum_send_pow'] = 5

View File

@ -10,7 +10,6 @@ conf = json.load(open('static-data/default_config.json', 'r'))
block_pow = int(input("Block POW level:"))
conf['general']['security_level'] = int(input("Security level:"))
conf['transports']['tor'] = False
if input('Use Tor? y/n').lower() == 'y':
conf['transports']['tor'] = True
@ -20,15 +19,11 @@ if input('Use Tor? y/n').lower() == 'y':
conf['tor']['existing_control_password'] = input("Tor pass:")
conf['tor']['existing_socks_port'] = int(input("Existing socks port:"))
conf['general']['dev_mode'] = True
conf['general']['insert_deniable_blocks'] = False
conf['general']['random_bind_ip'] = False
conf['onboarding']['done'] = True
conf['general']['minimum_block_pow'] = block_pow
conf['general']['minimum_send_pow'] = block_pow
conf['general']['use_bootstrap_list'] = False
if input("Use bootstrap list? y/n").lower() == 'y':
conf['general']['use_bootstrap_list'] = True
conf['log']['file']['remove_on_exit'] = False
conf['ui']['animated_background'] = False
if input('Stat reporting? y/n') == 'y':

View File

@ -1,41 +0,0 @@
#!/usr/bin/env python3
import sys
import os
import stem
from stem import process
from stem.control import Controller
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
try:
sys.argv[1]
except IndexError:
sys.exit(1)
tor_process = process.launch_tor_with_config(
completion_percent=0,
config = {
'ControlPort': '2778',
'DisableNetwork': '1',
'Log': [
'NOTICE stdout',
'ERR file /tmp/tor_error_log',
],
},
)
with Controller.from_port('127.0.0.1', 2778) as controller:
controller.authenticate()
for i in range(1024, 1024 + int(sys.argv[1])):
hs = controller.create_ephemeral_hidden_service(
{80: i},
key_type='NEW',
key_content='ED25519-V3',
await_publication=False,
detached=True)
print(hs.service_id + ".onion")
controller.remove_ephemeral_hidden_service(hs.service_id)
tor_process.kill()

View File

@ -1,21 +0,0 @@
#!/usr/bin/env python3
"""Generate a 16 word passphase with 256 bits of entropy.
Specify true to reduce to 128 bits"""
import sys
import niceware
byte_count = 32 # 256 bits of entropy with niceware
arg = False
try:
arg = sys.argv[1].lower()
if arg == 'true':
byte_count = 16
except IndexError: pass
print(' '.join(niceware.generate_passphrase(byte_count)))

View File

@ -1,50 +0,0 @@
#!/usr/bin/env python3
"""Craft and send requests to the local client API"""
import sys
import os
import time
from threading import Thread
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
import filepaths
import config
config.reload()
with open(filepaths.private_API_host_file, 'r') as host:
hostname = host.read()
port = config.get("client.client.port", 0)
if not port:
print("Could not get port for Onionr UI. Try again")
sys.exit(1)
torrc = f"""
HiddenServiceDir remote-onionr-hs
HiddenServicePort 80 {hostname}:{port}
"""
with open("remote-onionr-torrc", "w") as torrc_f:
torrc_f.write(torrc)
def show_onion():
while True:
time.sleep(1)
try:
with open("remote-onionr-hs/hostname", "r") as f:
o = f.read()
print("UI Onion (Keep secret):", o)
config.set("ui.public_remote_enabled", True)
config.set("ui.public_remote_hosts", [o])
config.save()
break
except FileNotFoundError:
pass
Thread(target=show_onion, daemon=True).start()
os.system("tor -f remote-onionr-torrc")

View File

@ -1,16 +0,0 @@
import sys
import os
import stem
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
from coredb.blockmetadb import get_block_list
from onionrblocks.onionrblockapi import Block
for bl in get_block_list():
bl_obj = Block(bl, decrypt=False)
b_type = bl_obj.getType()
if not b_type:
b_type = "encrypted"
print(bl + " - " + str(bl_obj.date) + " - " + b_type)

View File

@ -1,40 +0,0 @@
import sys
import os
import stem
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
from onionrutils import stringvalidators
from onionrutils import basicrequests
from stem.control import Controller
onionr_ip = input("onionr ip address: ")
onionr_port = int(input("Enter onionr public api port: "))
controller = Controller.from_port('127.0.0.1', int(input("Enter tor controller port: ")))
controller.authenticate()
node = input("Enter node to attack. Note that you legally must use your own, and even that might lead to technical or legal issues: ")
assert stringvalidators.validate_transport(node)
socks = input("Socks:")
adders = set([])
for i in range(int(input("Sybil addresses: "))):
response = controller.create_ephemeral_hidden_service({80: f'{onionr_ip}:{onionr_port}'}, await_publication=True)
#print(i, response.service_id)
adders.add(response.service_id)
for x in adders:
x += '.onion'
print(f"Introducing {x} to {node}")
basicrequests.do_post_request(
f'http://{node}/announce',
data = {'node': x},
port=socks)

View File

@ -1,12 +0,0 @@
#!/usr/bin/env python3
import sys
import os
if not os.path.exists('onionr.sh'):
os.chdir('../')
sys.path.append("src/")
import onionrblocks
expire = 600
print(onionrblocks.insert(data=os.urandom(32), expire=expire))

View File

@ -15,15 +15,16 @@ try:
except ImportError:
pass
import os
import cProfile
import threading
onionr_profiling = os.getenv("ONIONR_PROFILING", False)
import sys
try:
import sqlite3
except ModuleNotFoundError:
sys.stderr.write(
'Error, Onionr requires Sqlite3-enabled Python.\n' +
'https://stackoverflow.com/a/1875095\n')
sys.exit(1)
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -43,6 +44,29 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import locale # noqa
locale.setlocale(locale.LC_ALL, '') # noqa
import traceback
import signal
def sigusr_stacktrace(signum, frame):
"""Print stacktrace on SIGUSR1"""
stack_trace_file = os.getenv('ONIONR_STACK_TRACE_FILE', False)
for th in threading.enumerate():
if stack_trace_file:
with open(stack_trace_file, 'a') as f:
f.write(f'Thread: {th.name}')
f.write('-' * 44 + '')
traceback.print_stack(sys._current_frames()[th.ident], file=f)
else:
print(f'Thread: {th.name}')
print('-' * 44)
traceback.print_stack(sys._current_frames()[th.ident])
#print(traceback.format_stack(frame))
signal.signal(signal.SIGUSR1, sigusr_stacktrace)
# Importing initailzes logging
from logger import log as logging
ran_as_script = False
if __name__ == "__main__": ran_as_script = True
@ -73,7 +97,6 @@ if sys.version_info[0] == 2 or sys.version_info[1] < min_ver:
from utils import createdirs
createdirs.create_dirs()
import bigbrother # noqa
from onionrcommands import parser # noqa
from onionrplugins import onionrevents as events # noqa
@ -83,23 +106,21 @@ import config # noqa
from utils import identifyhome # noqa
import filepaths # noqa
if config.get('advanced.security_auditing', True):
try:
bigbrother.enable_ministries()
except onionrexceptions.PythonVersion:
pass
def onionr_main():
"""Onionr entrypoint, start command processor
Entrypoint for daemon is commands/daemonlaunch/__init__.py
"""
events.event('beforecmdparsing', threaded=False)
parser.register()
if ran_as_script:
onionr_main()
if onionr_profiling:
cProfile.run('onionr_main()')
else:
onionr_main()
config.reload()

View File

@ -1,87 +0,0 @@
"""Onionr - Private P2P Communication.
Prevent eval/exec/os.system and log it
"""
import base64
import platform
import logger
from utils import identifyhome
from onionrexceptions import ArbitraryCodeExec
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
untrusted_exec = True
def block_system(cmd):
"""Prevent os.system except for whitelisted commands+contexts."""
logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True)
logger.warn(f'POSSIBLE EXPLOIT: shell command not in whitelist: {cmd}')
raise ArbitraryCodeExec('os.system command not in whitelist')
def block_exec(event, info):
"""Prevent arbitrary code execution in eval/exec and log it."""
# because libraries have stupid amounts of compile/exec/eval,
# We have to use a whitelist where it can be tolerated
# Generally better than nothing, not a silver bullet
if untrusted_exec:
return
whitelisted_code = [
'netrc.py',
'shlex.py',
'gzip.py',
'<werkzeug routing>',
'werkzeug/test.py',
'multiprocessing/popen_fork.py',
'multiprocessing/util.py',
'multiprocessing/connection.py',
'multiprocessing/queues.py',
'multiprocessing/synchronize.py',
'onionrutils/escapeansi.py',
'stem/connection.py',
'stem/response/add_onion.py',
'stem/response/authchallenge.py',
'stem/response/getinfo.py',
'stem/response/getconf.py',
'stem/response/mapaddress.py',
'stem/response/protocolinfo.py',
'apport/__init__.py',
'apport/report.py'
]
whitelisted_source = [
'ZABaAGQBZAJsAW0CWgIBAHoGZAFkA2wDWgRXAG4LBABlBXkZAQABAAEAZARaBlkAbgN3AGQFWgZkAWQGbAdtCFoIAQBkAWQDbAlaCWQBZAdsCm0LWgwBAAkAZQmgDWQIZAWhAnM1ZARaBmUIgwBkCRcAWg5kEmQMZQ9kDWUPZgRkDmQPhAVaEGQTZBBkEYQBWhFkA1MA',
'RwBkAGQBhABkAYMCWgBkAlMA',
'ZABaAGQBZAJsAVoBZAFkAmwCWgJkAWQCbANaA2QBZAJsBFoEZAFkAmwFWgVkAWQCbAZaBmQBZAJsB1oIZAFkAmwJWghkAWQCbApaCGQBZAJsC1oIZANaDGQEWg1kBWQCZAJkBmQCZQ1kB2QIZAJmCWQJZAqEAVoOZAVkBmQCZQ1kB2QIZgZkC2QMhAFaD2QCUwA=',
'ZABaAGQBZAJsAVoBZAFkAmwCWgJkAWQCbANaA2QBZAJsBFoEZAFkAmwFWgVkAWQCbAZaBmQBZAJsB1oIZAFkAmwJWghkAWQCbApaCGQBZANsC20MWgxtDVoNbQ5aDm0PWg9tEFoQbRFaEQEAZARaEmQFWhNkBmQCZAJkB2QCZRNkCGQJZAJmCWQKZRRkC2UPZRBlFBkAGQBkDGUPZRQZAGQNZRVkDmUPZQ1lFGcBZAJmAhkAGQBkD2UVZBBlFmQRZRZkEmUPZRQZAGQTZQRqF2YUZBRkFYQFWhhkBmQHZAJlE2QIZAlmBmQWZQ5lFGURZRRlEGUUGQBmAhkAZgIZAGQKZRRkDWUVZA5lD2UNZRRnAWQCZgIZABkAZA9lFWQQZRZkEWUWZBNlBGoXZhBkF2QYhAVaGWQCUwA='
]
home = identifyhome.identify_home()
code_b64 = base64.b64encode(info[0].co_code).decode()
if code_b64 in whitelisted_source:
return
for source in whitelisted_code:
if info[0].co_filename.endswith(source):
return
if 'plugins/' in info[0].co_filename:
return
logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True)
logger.warn('POSSIBLE EXPLOIT DETECTED: ' + info[0].co_filename)
logger.warn('Prevented exec/eval. Report this with the sample below')
logger.warn(f'{event} code in base64 format: {code_b64}')
raise ArbitraryCodeExec("Arbitrary code (eval/exec) detected.")

View File

@ -1,6 +1,7 @@
from typing import Callable, Generator, List
from onionrblocks import Block
from onionrplugins import onionrevents
import db
@ -15,8 +16,9 @@ block_storage_observers: List[Callable] = []
def add_block_to_db(block: Block):
# Raises db.DuplicateKey if dupe
db.set_if_new(block_db_path, block.id, block.raw)
onionrevents.event('before_block_db_add', block, threaded=False)
db.set_if_new(block_db_path, block.id, block.raw) # Raises db.DuplicateKey if dupe
onionrevents.event('after_block_db_add', block, threaded=False)
def has_block(block_hash):

View File

@ -2,7 +2,7 @@ from typing import Set
from onionrblocks import Block
import logger
from logger import log as logging
from .deleteblock import delete_block
from .getblocks import get_blocks_after_timestamp
@ -18,7 +18,7 @@ def clean_block_database():
Block(block.id, block.raw, auto_verify=True)
except ValueError: # block expired
remove_set.add(block)
if len(remove_set):
logger.info(f"Cleaning {len(remove_set)} blocks", terminal=True)
logging.info(f"Cleaning {len(remove_set)} blocks")
[i for i in map(delete_block, remove_set)]

View File

@ -6,7 +6,12 @@ from onionrblocks import Block
from .dbpath import block_db_path
def get_blocks_by_type(block_type: str) -> "Generator[Block]":
try:
block_type = block_type.decode('utf-8')
except AttributeError:
pass
block_db = db.get_db_obj(block_db_path, 'u')
for block_hash in db.list_keys(block_db_path):
block = Block(block_hash, block_db[block_hash], auto_verify=False)
@ -25,4 +30,4 @@ def get_blocks_after_timestamp(
if block_type == block.type:
yield block
else:
yield block
yield block

View File

@ -6,10 +6,9 @@ import os
from json import JSONDecodeError
import ujson as json
import logger
from logger import log as logging
import filepaths
from . import onboarding
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -107,7 +106,7 @@ def save():
with open(get_config_file(), 'w', encoding="utf8") as configfile:
json.dump(get_config(), configfile, indent=2)
except JSONDecodeError:
logger.warn('Failed to write to configuration file.')
logging.warn('Failed to write to configuration file.')
def reload():
@ -118,7 +117,7 @@ def reload():
set_config(json.loads(configfile.read()))
except (FileNotFoundError, JSONDecodeError) as e:
pass
#logger.debug('Failed to parse configuration file.')
#logging.debug('Failed to parse configuration file.')
def get_config():

View File

@ -1,79 +0,0 @@
"""Onionr - Private P2P Communication.
Setup config from onboarding choices
"""
from pathlib import Path
from typing import Union
from filepaths import onboarding_mark_file
from onionrtypes import JSONSerializable
from onionrtypes import OnboardingConfig
import config
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def _get_val_or_none(json: dict, key: str) -> Union[None, JSONSerializable]:
try:
return json['configInfo'][key]
except KeyError:
return None
def set_config_from_onboarding(config_settings: OnboardingConfig):
get = _get_val_or_none
config.reload()
if get(config_settings, 'optimize'):
config.set('ui.animated_background', False)
config.set('general.insert_deniable_blocks', False)
if get(config_settings, 'stateTarget') or not get(config_settings,
'networkContrib'):
config.set('general.security_level', 1)
if get(config_settings, 'localThreat'):
config.set('general.security_level', 3)
config.set('transports.lan', False)
config.set('ui.theme', 'light')
if get(config_settings, 'useDark'):
config.set('ui.theme', 'dark')
disabled = config.get('plugins.disabled', [])
if not get(config_settings, 'circles') or \
config.get('general.security_level') > 0:
disabled.append('flow')
if not get(config_settings, 'mail'):
disabled.append('pms')
config.set('plugins.disabled', disabled)
config.set('general.store_plaintext_blocks',
get(config_settings, 'plainContrib'))
config.set('onboarding.done', True, savefile=True)
def set_onboarding_finished():
"""Create the onboarding completed setting file"""
Path(onboarding_mark_file).touch()
def is_onboarding_finished() -> bool:
return True

View File

@ -1 +0,0 @@
from . import keydb

View File

@ -1,9 +0,0 @@
from utils import identifyhome
import filepaths
home = identifyhome.identify_home()
if not home.endswith('/'): home += '/'
address_info_db = '%saddress.db' % (home,)
user_id_info_db = '%susers.db' % (home,)
forward_keys_db = '%sforward-keys.db' % (home,)
blacklist_db = '%sblacklist.db' % (home,)

View File

@ -1 +0,0 @@
from . import addkeys, listkeys, removekeys, userinfo

View File

@ -1,55 +0,0 @@
"""Onionr - Private P2P Communication.
add user keys or transport addresses
"""
import sqlite3
from onionrutils import stringvalidators
from . import listkeys
from .. import dbfiles
import onionrcrypto
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def add_pub_key(peerID, name=''):
"""Add a public key to the key database (misleading function name)."""
if peerID in listkeys.list_pub_keys() or peerID == onionrcrypto.pub_key:
raise ValueError("specified id is already known")
# This function simply adds a peer to the DB
if not stringvalidators.validate_pub_key(peerID):
return False
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
hashID = ""
c = conn.cursor()
t = (peerID, name, 'unknown', hashID, 0)
for i in c.execute("SELECT * FROM peers WHERE id = ?;", (peerID,)):
try:
if i[0] == peerID:
conn.close()
return False
except ValueError:
pass
except IndexError:
pass
c.execute('INSERT INTO peers (id, name, dateSeen, hashID, trust) VALUES(?, ?, ?, ?, ?);', t)
conn.commit()
conn.close()
return True

View File

@ -1,63 +0,0 @@
"""
Onionr - Private P2P Communication
get lists for user keys
"""
import sqlite3
import logger
from onionrutils import epoch
import onionrvalues
from .. import dbfiles
from . import userinfo
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def list_pub_keys(randomOrder=True, getPow=False, trust=0):
"""
Return a list of public keys (misleading function name)
randomOrder determines if the list should be in a random order
trust sets the minimum trust to list
"""
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
payload = ''
if trust not in (0, 1, 2):
logger.error('Tried to select invalid trust.')
return
if randomOrder:
payload = 'SELECT * FROM peers WHERE trust >= ? ORDER BY RANDOM();'
else:
payload = 'SELECT * FROM peers WHERE trust >= ?;'
peer_list = []
for i in c.execute(payload, (trust,)):
try:
if len(i[0]) != 0:
if getPow:
peer_list.append(i[0] + '-' + i[1])
else:
peer_list.append(i[0])
except TypeError:
pass
conn.close()
return peer_list

View File

@ -1,43 +0,0 @@
"""
Onionr - Private P2P Communication
Remove a transport address but don't ban them
"""
import sqlite3
from onionrplugins import onionrevents as events
from onionrutils import stringvalidators
from onionrutils import mnemonickeys
from .. import dbfiles
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def remove_user(pubkey: str)->bool:
"""Remove a user from the user database"""
pubkey = mnemonickeys.get_base32(pubkey)
if stringvalidators.validate_pub_key(pubkey):
conn = sqlite3.connect(
dbfiles.user_id_info_db,
timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
t = (pubkey,)
c.execute('Delete from peers where id=?;', t)
conn.commit()
conn.close()
return True
else:
return False

View File

@ -1,74 +0,0 @@
"""
Onionr - Private P2P Communication
get or set information about a user id
"""
import sqlite3
from .. import dbfiles
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def get_user_info(peer, info):
"""
Get info about a peer from their database entry
id text 0
name text, 1
adders text, 2
dateSeen not null, 3
trust int 4
hashID text 5
"""
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
command = (peer,)
infoNumbers = {'id': 0, 'name': 1, 'adders': 2, 'dateSeen': 3, 'trust': 4, 'hashID': 5}
info = infoNumbers[info]
iterCount = 0
retVal = ''
for row in c.execute('SELECT * FROM peers WHERE id=?;', command):
for i in row:
if iterCount == info:
retVal = i
break
else:
iterCount += 1
conn.close()
return retVal
def set_peer_info(peer, key, data):
"""
Update a peer for a key
"""
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
command = (data, peer)
if key not in ('id', 'name', 'pubkey', 'forwardKey', 'dateSeen', 'trust'):
raise ValueError("Got invalid database key when setting peer info")
c.execute('UPDATE peers SET ' + key + ' = ? WHERE id=?', command)
conn.commit()
conn.close()
set_user_info = set_peer_info

View File

@ -7,36 +7,8 @@ app_root = os.path.dirname(os.path.realpath(__file__)) + '/../../'
gossip_server_socket_file = home + 'gossip-server.sock'
usage_file = home + 'disk-usage.txt'
contacts_location = home + 'contacts/'
public_API_host_file = home + 'public-host.txt'
private_API_host_file = home + 'private-host.txt'
bootstrap_file_location = 'static-data/bootstrap-nodes.txt'
data_nonce_file = home + 'block-nonces.dat'
forward_keys_file = home + 'forward-keys.db'
cached_storage = home + 'cachedstorage.dat'
export_location = home + 'block-export/'
upload_list = home + 'upload-list.json'
config_file = home + 'config.json'
daemon_mark_file = home + '/daemon-true.txt'
lock_file = home + 'onionr.lock'
pid_file = home + 'onionr.pid'
site_cache = home + 'onionr-sites.txt'
tor_hs_loc = home + 'hs/'
tor_hs_address_file = home + 'hs/hostname'
data_nonce_file = home + 'block-nonces.dat'
keys_file = home + 'keys.txt'
onboarding_mark_file = home + 'onboarding-completed'
log_file = home + 'onionr.log'
ephemeral_services_file = home + 'ephemeral-services.list'
restarting_indicator = home + "is-restarting"
block_database = home + "blocks.db"

View File

@ -1,6 +1,7 @@
import threading
from time import sleep
from typing import TYPE_CHECKING, Set, Tuple
from logger import log as logging
if TYPE_CHECKING:
from ordered_set import OrderedSet
@ -11,7 +12,6 @@ if TYPE_CHECKING:
from onionrthreads import add_onionr_thread
import onionrplugins
import logger
from .connectpeer import connect_peer
from .client import start_gossip_client
@ -56,4 +56,4 @@ def start_gossip_threads():
sleep(60)
if len(gossip_peer_set):
return
logger.error("Could not connect to any peers :(", terminal=True)
logging.error("Could not connect to any peers :(")

View File

@ -21,7 +21,7 @@ if TYPE_CHECKING:
from ..peer import Peer
from ordered_set import OrderedSet
import logger
from logger import log as logging
import config
import onionrplugins
from ..commands import GossipCommands
@ -59,22 +59,22 @@ def block_queue_processing():
while not len(gossip_peer_set):
sleep(0.2)
sleep(1)
if dandelion_phase.remaining_time() <= 15:
#logger.debug("Sleeping", terminal=True)
#logging.debug("Sleeping")
sleep(dandelion_phase.remaining_time())
if dandelion_phase.is_stem_phase() and config.get('security.dandelion.enabled', True):
logger.debug("Entering stem phase", terminal=True)
logging.debug("Entering stem phase")
try:
# Stem out blocks for (roughly) remaining epoch time
asyncio.run(stem_out(dandelion_phase))
except TimeoutError:
pass
except Exception:
logger.error(traceback.format_exc(), terminal=True)
logging.error(traceback.format_exc())
pass
else:
#logger.debug("Entering fluff phase", terminal=True)
#logging.debug("Entering fluff phase")
# Add block to primary block db, where the diffuser can read it
sleep(0.1)
store_blocks(dandelion_phase)
@ -101,7 +101,7 @@ def start_gossip_client():
# transport plugin handles the new peer
add_onionr_thread(
get_new_peers,
60, 'get_new_peers', initial_sleep=120)
120, 'get_new_peers', initial_sleep=120)
# Start a new thread to stream blocks from peers
# These blocks are being diffused and are stored in

View File

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .. import Peer
import logger
from logger import log as logging
import onionrplugins
from ..commands import GossipCommands, command_to_byte
@ -28,7 +28,7 @@ def do_announce():
sock.sendall(command_to_byte(GossipCommands.ANNOUNCE))
sock.sendall(our_transport_address)
if int.from_bytes(sock.recv(1), 'big') != 1:
logger.warn(
logging.warn(
f"Could not announce with {announce_peer.transport_address}")
sock.close()

View File

@ -11,7 +11,7 @@ from ordered_set import OrderedSet
import config
from onionrthreads import add_delayed_thread
from blockdb import add_block_to_db
import logger
from logger import log as logging
from ...constants import BLACKHOLE_EVADE_TIMER_SECS, OUTBOUND_DANDELION_EDGES
from ...commands import GossipCommands, command_to_byte
@ -45,9 +45,9 @@ async def _setup_edge(
try:
s = peer.get_socket(12)
except TimeoutError:
logger.debug(f"{peer.transport_address} timed out when trying stemout")
logging.debug(f"{peer.transport_address} timed out when trying stemout")
except Exception:
logger.debug(traceback.format_exc())
logging.debug(traceback.format_exc())
return
try:
@ -56,18 +56,18 @@ async def _setup_edge(
if s.recv(1) == dandelion.StemAcceptResult.DENY:
raise StemConnectionDenied
except TimeoutError:
logger.debug(
"Peer timed out when establishing stem connection", terminal=True)
logger.debug(traceback.format_exc())
logging.debug(
"Peer timed out when establishing stem connection")
logging.debug(traceback.format_exc())
except StemConnectionDenied:
logger.debug(
logging.debug(
"Stem connection denied (peer has too many) " +
f"{peer.transport_address}")
logger.debug(traceback.format_exc())
logging.debug(traceback.format_exc())
except Exception:
logger.warn(
logging.warn(
"Error asking peer to establish stem connection" +
traceback.format_exc(), terminal=True)
traceback.format_exc())
else:
# Return peer socket if it is in stem reception mode successfully
return s
@ -113,10 +113,10 @@ async def stem_out(d_phase: 'DandelionPhase'):
await _setup_edge(gossip_peer_set, tried_edges))
except NotEnoughEdges:
# No possible edges at this point (edges < OUTBOUND_DANDELION_EDGE)
#logger.debug(
#logging.debug(
# "Making too few edges for stemout " +
# "this is bad for anonymity if frequent.",
# terminal=True)
# )
if strict_dandelion:
not_enough_edges = True
else:
@ -133,10 +133,10 @@ async def stem_out(d_phase: 'DandelionPhase'):
else:
# Ran out of time for stem phase
if not d_phase.is_stem_phase() or d_phase.remaining_time() < 5:
logger.error(
logging.error(
"Did not stem out any blocks in time, " +
"if this happens regularly you may be under attack",
terminal=False)
)
for s in peer_sockets:
if s:
s.close()
@ -155,7 +155,7 @@ async def stem_out(d_phase: 'DandelionPhase'):
except Empty:
pass
except Exception:
logger.warn(traceback.format_exc())
logging.warn(traceback.format_exc())
else:
# stream routine exited early
pass

View File

@ -4,7 +4,7 @@ from queue import Empty
from typing import TYPE_CHECKING
import logger
from logger import log as logging
from ...constants import BLOCK_ID_SIZE, BLOCK_MAX_SIZE, BLOCK_SIZE_LEN
if TYPE_CHECKING:
@ -22,7 +22,7 @@ async def do_stem_stream(
remaining_time = d_phase.remaining_time()
my_phase_id = d_phase.phase_id
while remaining_time > 1 and my_phase_id == d_phase.phase_id:
# Primary client component that communicate's with gossip.server.acceptstem
remaining_time = d_phase.remaining_time()
@ -35,7 +35,7 @@ async def do_stem_stream(
await sleep(1)
else:
break
logger.info("Sending block over dandelion++", terminal=True)
logging.info("Sending block over dandelion++")
block_size = str(len(bl.raw)).zfill(BLOCK_SIZE_LEN)
def _send_it():

View File

@ -6,9 +6,7 @@ if TYPE_CHECKING:
from socket import socket
from onionrplugins import onionrevents
import logger
from socks import GeneralProxyError
from logger import log as logging
from ..peer import Peer
from ..commands import GossipCommands, command_to_byte
@ -23,12 +21,9 @@ def _do_ask_peer(peer):
try:
_ask_peer(peer)
except TimeoutError:
logger.debug("Timed out when asking for new peers")
except GeneralProxyError:
logger.debug("Proxy error")
logger.debug(format_exc(), terminal=True)
logging.debug("Timed out when asking for new peers")
except Exception:
logger.error(format_exc(), terminal=True)
logging.error(format_exc())
def _ask_peer(peer):
s: 'socket' = peer.get_socket(12)
@ -49,14 +44,14 @@ def _ask_peer(peer):
'address': peer,
'callback': connectpeer.connect_peer
}
logger.info("Got new peer from exchange " + peer.decode('utf-8'), terminal=True)
#logging.info("Got new peer from exchange " + peer.decode('utf-8'))
onionrevents.event('announce_rec', data=connect_data, threaded=True)
s.close()
def get_new_peers():
if not len(gossip_peer_set):
logger.debug("Peer set empty, cannot get new peers")
logging.debug("Peer set empty, cannot get new peers")
return
# Deep copy the peer list
@ -79,7 +74,7 @@ def get_new_peers():
threads = []
for peer in peers_we_ask:
t = Thread(
target=_do_ask_peer,
target=_do_ask_peer,
args=[peer], daemon=True, name='_do_ask_peer')
t.start()
threads.append(t)

View File

@ -3,6 +3,7 @@ from threading import Thread
from queue import Queue
from queue import Empty
from onionrplugins.onionrevents import event
import blockdb
if TYPE_CHECKING:
@ -32,9 +33,9 @@ def store_blocks(dandelion_phase: 'DandelionPhase'):
while not dandelion_phase.is_stem_phase() \
and dandelion_phase.remaining_time() > 1:
try:
blockdb.add_block_to_db(
new_queue.get(timeout=dandelion_phase.remaining_time() + 1)
)
bl = new_queue.get(timeout=dandelion_phase.remaining_time() + 1)
blockdb.add_block_to_db(bl)
event('gotblock', data=bl, threaded=True)
event(f'gotblock{bl.type}', data=bl, threaded=True)
except Empty:
pass

View File

@ -22,7 +22,7 @@ if TYPE_CHECKING:
from ordered_set import OrderedSet
import logger
from logger import log as logging
import onionrblocks
from ...peerset import gossip_peer_set
@ -67,11 +67,11 @@ def stream_from_peers():
stream_times = 100
try:
sock = peer.get_socket(CONNECT_TIMEOUT)
except ConnectionRefusedError:
except (TimeoutError, ConnectionRefusedError) as _:
need_socket_lock.release()
return
except Exception:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())
need_socket_lock.release()
return
try:
@ -83,7 +83,7 @@ def stream_from_peers():
while stream_times >= stream_counter:
stream_counter += 1
logger.debug("Reading block of id in stream with " + peer.transport_address, terminal=True)
#logging.debug("Reading block of id in stream with " + peer.transport_address)
sock.settimeout(5)
block_id = sock.recv(BLOCK_ID_SIZE)
if blockdb.has_block(block_id):
@ -91,22 +91,22 @@ def stream_from_peers():
continue
sock.sendall(int(1).to_bytes(1, 'big'))
#logger.debug("Reading block size in stream", terminal=True)
#logging.debug("Reading block size in stream")
sock.settimeout(5)
block_size = int(sock.recv(BLOCK_SIZE_LEN))
if block_size > BLOCK_MAX_SIZE or block_size <= 0:
logger.warn(
logging.warn(
f"Peer {peer.transport_address} " +
"reported block size out of range")
break
sock.settimeout(5)
block_data = sock.recv(block_size)
#logger.debug(
#logging.debug(
# "We got a block from stream, assuming it is valid",
# terminal=True)
# )
try:
blockdb.add_block_to_db(
onionrblocks.Block(
@ -118,19 +118,20 @@ def stream_from_peers():
raise
# Tell them to keep streaming
sock.sendall(int(1).to_bytes(1, 'big'))
except (BrokenPipeError, TimeoutError) as e:
except (BrokenPipeError, TimeoutError, ConnectionError) as e:
pass
#logger.debug(f"{e} when streaming from peers", terminal=True)
#logger.debug(traceback.format_exc())
#logging.debug(f"{e} when streaming from peers")
#logging.debug(traceback.format_exc())
except Exception:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())
finally:
sock.close()
need_socket_lock.release()
# spawn stream threads infinitely
while True:
if not gossip_peer_set:
sleep(2)
available_set = gossip_peer_set - tried_peers
if not len(available_set) and len(tried_peers):
try:
@ -157,4 +158,4 @@ def stream_from_peers():
except IndexError:
need_socket_lock.release()
break

View File

@ -2,7 +2,7 @@ import traceback
from gossip.commands import GossipCommands, command_to_byte
from .peerset import gossip_peer_set
import logger
from logger import log as logging
def connect_peer(peer):
@ -11,12 +11,12 @@ def connect_peer(peer):
try:
s = peer.get_socket(120)
except Exception:
logger.warn(f"Could not connect to {peer.transport_address}")
logger.warn(traceback.format_exc())
logging.warn(f"Could not connect to {peer.transport_address}")
logging.warn(traceback.format_exc())
else:
with s:
s.sendall(command_to_byte(GossipCommands.PING))
if s.recv(4).decode('utf-8') == 'PONG':
gossip_peer_set.add(peer)
logger.info(f"connected to {peer.transport_address}", terminal=True)
logging.info(f"connected to {peer.transport_address}")

View File

@ -12,7 +12,7 @@ from gossip import constants
from ..connectpeer import connect_peer
from onionrplugins import onionrevents
import logger
from logger import log as logging
if TYPE_CHECKING:
from onionrblocks import Block
@ -88,9 +88,9 @@ def gossip_server():
try:
await diffuse_blocks(reader, writer)
except Exception:
logger.warn(
logging.warn(
f"Err streaming blocks\n{traceback.format_exc()}",
terminal=True)
)
case GossipCommands.PUT_BLOCKS:
# Pick block queue & append stemmed blocks to it
try:
@ -99,18 +99,18 @@ def gossip_server():
inbound_dandelion_edge_count)
except asyncio.exceptions.TimeoutError:
pass
logger.debug(
logging.debug(
"Inbound edge timed out when steming blocks to us",
terminal=True)
)
except asyncio.exceptions.IncompleteReadError:
pass
logger.debug(
logging.debug(
"Inbound edge timed out (Incomplete Read) when steming blocks to us",
terminal=True)
)
except Exception:
logger.warn(
logging.warn(
f"Err accepting stem blocks\n{traceback.format_exc()}",
terminal=True)
)
# Subtract dandelion edge, make sure >=0
inbound_dandelion_edge_count[0] = \
max(inbound_dandelion_edge_count[0] - 1, 0)
@ -120,14 +120,13 @@ def gossip_server():
if blockdb.has_block(block_id):
writer.write(int(0).to_bytes(1, 'big'))
else:
writer.write(int(1).to_bytes(1, 'big'))
await writer.drain()
block_size = int(await asyncio.wait_for(reader.readexactly(constants.BLOCK_SIZE_LEN), 30))
block_data = await reader.readexactly(block_size)
Thread(
target=add_block_to_db,
target=add_block_to_db,
args=[
Block(block_id, block_data, auto_verify=True)]
).start()
@ -137,6 +136,7 @@ def gossip_server():
await writer.drain()
except BrokenPipeError:
pass
writer.close()
async def main():

View File

@ -1,3 +1,4 @@
import traceback
from typing import TYPE_CHECKING
from typing import List
import secrets
@ -5,7 +6,7 @@ from asyncio import wait_for
from onionrblocks import Block
import logger
from logger import log as logging
from ..dandelion import StemAcceptResult
from ..constants import BLOCK_ID_SIZE, BLOCK_SIZE_LEN, BLOCK_MAX_SIZE
from ..constants import MAX_INBOUND_DANDELION_EDGE, MAX_STEM_BLOCKS_PER_STREAM
@ -35,13 +36,13 @@ async def accept_stem_blocks(
for _ in range(MAX_STEM_BLOCKS_PER_STREAM):
read_routine = reader.readexactly(BLOCK_ID_SIZE)
logger.debug(f"Reading block id in stem server", terminal=True)
#logging.debug(f"Reading block id in stem server")
block_id = await wait_for(read_routine, base_wait_timeout)
block_id = block_id.decode('utf-8')
if not block_id:
break
logger.debug(f"Reading block size in stem server", terminal=True)
#logging.debug(f"Reading block size in stem server")
block_size = (await wait_for(
reader.readexactly(BLOCK_SIZE_LEN),
base_wait_timeout)).decode('utf-8')
@ -54,17 +55,25 @@ async def accept_stem_blocks(
if block_size > BLOCK_MAX_SIZE:
raise ValueError("Max block size")
logger.debug(f"Reading block of size {block_size} in stem server", terminal=True)
#logging.debug(f"Reading block of size {block_size} in stem server")
raw_block: bytes = await wait_for(
reader.readexactly(block_size), base_wait_timeout * 6)
if not raw_block:
break
logger.debug("Got a stem block, put into queue", terminal=True)
block_queue_to_use.put(
Block(block_id, raw_block, auto_verify=True)
)
try:
bl = Block(block_id, raw_block, auto_verify=True)
except Exception as e:
logging.warn(
f"Error in received stem block {block_id} {str(e)}")
logging.debug(traceback.format_exc())
break
logging.debug("Got a stem block, put into queue")
block_queue_to_use.put(bl)
# Regardless of stem phase, we add to queue
# Client will decide if they are to be stemmed

View File

@ -19,7 +19,7 @@ if TYPE_CHECKING:
from ..constants import BLOCK_MAX_SIZE, BLOCK_SIZE_LEN
from ..constants import BLOCK_STREAM_OFFSET_DIGITS
import logger
from logger import log as logging
import blockdb
from blockdb import get_blocks_after_timestamp, block_storage_observers
"""
@ -103,5 +103,5 @@ async def diffuse_blocks(reader: 'StreamReader', writer: 'StreamWriter'):
except ConnectionResetError:
pass
except Exception:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())

View File

@ -1,81 +0,0 @@
"""Onionr - Private P2P Communication.
Load, save, and delete the user's public key pairs (does not handle peer keys)
"""
from onionrutils import bytesconverter
from onionrcrypto import generate
import filepaths
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
class KeyManager:
def __init__(self):
self.keyFile = filepaths.keys_file
def addKey(self, pubKey=None, privKey=None):
"""Add a new key pair.
either specified or None to generate a new pair automatically
"""
if type(pubKey) is type(None) and type(privKey) is type(None):
pubKey, privKey = generate.generate_pub_key()
pubKey = bytesconverter.bytes_to_str(pubKey)
privKey = bytesconverter.bytes_to_str(privKey)
try:
if pubKey in self.getPubkeyList():
raise ValueError('Pubkey already in list: %s' % (pubKey,))
except FileNotFoundError:
pass
with open(self.keyFile, "a") as keyFile:
keyFile.write(pubKey + ',' + privKey + '\n')
return (pubKey, privKey)
def removeKey(self, pubKey):
"""Remove a key pair by pubkey"""
keyList = self.getPubkeyList()
keyData = ''
try:
keyList.remove(pubKey)
except ValueError:
return False
else:
keyData = ','.join(keyList)
with open(self.keyFile, "w") as keyFile:
keyFile.write(keyData)
def getPubkeyList(self):
"""Return a list of the user's keys"""
keyList = []
try:
with open(self.keyFile, "r") as keyFile:
keyData = keyFile.read()
except FileNotFoundError:
keyData = ''
keyData = keyData.split('\n')
for pair in keyData:
if len(pair) > 0:
keyList.append(pair.split(',')[0])
return keyList
def getPrivkey(self, pubKey):
privKey = None
with open(self.keyFile, "r") as keyFile:
keyData = keyFile.read()
for pair in keyData.split('\n'):
if pubKey in pair or pubKey.replace('=', '') in pair:
privKey = pair.split(',')[1]
return privKey

View File

@ -1,71 +1,92 @@
'''
Onionr - Private P2P Communication
"""
Onionr - Private P2P Communication
This file handles all operations involving logging
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
We use built in logging but with a custom formatter for colors and such
"""
import logging
import sys
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
from filepaths import log_file
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
import sys, traceback
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from . import colors, readline, log, raw, confirm, colors, settings
colors = colors.Colors
readline = readline.readline
log = log.log
raw = raw.raw
confirm = confirm.confirm
# credit: https://stackoverflow.com/a/384076
# license: https://creativecommons.org/licenses/by-sa/4.0/
class ConsoleFormatter(logging.Formatter):
# debug: when there is info that could be useful for debugging purposes only
def debug(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_DEBUG):
if settings.get_level() <= level:
log('/', data, timestamp = timestamp, prompt = prompt, terminal = terminal)
if not error is None:
debug('Error: ' + str(error) + parse_error())
grey = "\x1b[38;20m"
green = "\x1b[38;5;82m"
yellow = "\x1b[33;20m"
red = "\x1b[31;20m"
bold_red = "\x1b[31;1m"
reset = "\x1b[0m"
format_default = "%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
format_info = "%(message)s - (%(filename)s:%(lineno)d)"
# info: when there is something to notify the user of, such as the success of a process
def info(data: str, timestamp = False, prompt = True, terminal = False, level = settings.LEVEL_INFO):
if settings.get_level() <= level:
log('+', data, colors.fg.green, timestamp = timestamp, prompt = prompt, terminal = terminal)
FORMATS = {
logging.DEBUG: grey + format_default + reset,
logging.INFO: green + format_info + reset,
logging.WARNING: yellow + format_default + reset,
logging.ERROR: red + format_default + reset,
logging.CRITICAL: bold_red + format_default + reset
}
# warn: when there is a potential for something bad to happen
def warn(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_WARN):
if not error is None:
debug('Error: ' + str(error) + parse_error())
if settings.get_level() <= level:
log('!', data, colors.fg.orange, timestamp = timestamp, prompt = prompt, terminal = terminal)
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
# error: when only one function, module, or process of the program encountered a problem and must stop
def error(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_ERROR):
if settings.get_level() <= level:
log('-', data, colors.fg.red, timestamp = timestamp, fd = sys.stderr, prompt = prompt, terminal = terminal)
if not error is None:
debug('Error: ' + str(error) + parse_error())
class FileFormatter(logging.Formatter):
# fatal: when the something so bad has happened that the program must stop
def fatal(data: str, error = None, timestamp=True, prompt = True, terminal = False, level = settings.LEVEL_FATAL):
if not error is None:
debug('Error: ' + str(error) + parse_error(), terminal = terminal)
if settings.get_level() <= level:
log('#', data, colors.bg.red + colors.fg.green + colors.bold, timestamp = timestamp, fd = sys.stderr, prompt = prompt, terminal = terminal)
# returns a formatted error message
def parse_error():
details = traceback.extract_tb(sys.exc_info()[2])
output = ''
format_default = "%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
format_info = "%(message)s - (%(filename)s:%(lineno)d)"
for line in details:
output += '\n ... module %s in %s:%i' % (line[2], line[0], line[1])
FORMATS = {
logging.DEBUG: format_default,
logging.INFO: format_info,
logging.WARNING: format_default,
logging.ERROR: format_default,
logging.CRITICAL: format_default
}
return output
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
#logging.basicConfig(level=logging.ERROR, format='%(message)s ')
log = logging.getLogger('onionr')
log.setLevel(logging.INFO)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.INFO)
ch.setFormatter(ConsoleFormatter())
def enable_file_logging():
fh = logging.FileHandler(log_file)
fh.setLevel(logging.INFO)
fh.setFormatter(FileFormatter())
log.addHandler(fh)
def disable_console_logging():
log.removeHandler(ch)
def enable_console_logging():
log.addHandler(ch)
enable_console_logging()

View File

@ -1,60 +0,0 @@
'''
Onionr - Private P2P Communication
class to access ANSI control codes
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import re
class Colors:
'''
This class allows you to set the color if ANSI codes are supported
'''
reset='\033[0m'
bold='\033[01m'
disable='\033[02m'
underline='\033[04m'
reverse='\033[07m'
strikethrough='\033[09m'
invisible='\033[08m'
italics='\033[3m'
class fg:
black='\033[30m'
red='\033[31m'
green='\033[32m'
orange='\033[33m'
blue='\033[34m'
purple='\033[35m'
cyan='\033[36m'
lightgrey='\033[37m'
darkgrey='\033[90m'
lightred='\033[91m'
lightgreen='\033[92m'
yellow='\033[93m'
lightblue='\033[94m'
pink='\033[95m'
lightcyan='\033[96m'
class bg:
black='\033[40m'
red='\033[41m'
green='\033[42m'
orange='\033[43m'
blue='\033[44m'
purple='\033[45m'
cyan='\033[46m'
lightgrey='\033[47m'
@staticmethod
def filter(data):
return re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]').sub('', str(data))

View File

@ -1,54 +0,0 @@
'''
Onionr - Private P2P Communication
confirm y/n cli prompt
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import sys
from . import colors, settings
colors = colors.Colors
def confirm(default = 'y', message = 'Are you sure %s? '):
'''
Displays an "Are you sure" message, returns True for Y and False for N
message: The confirmation message, use %s for (y/n)
default: which to prefer-- y or n
'''
color = colors.fg.green + colors.bold
default = default.lower()
confirm = colors.bold
if default.startswith('y'):
confirm += '(Y/n)'
else:
confirm += '(y/N)'
confirm += colors.reset + color
output = colors.reset + str(color) + '... ' + colors.reset + str(message) + colors.reset
if not get_settings() & settings.USE_ANSI:
output = colors.filter(output)
sys.stdout.write(output.replace('%s', confirm))
inp = input().lower()
if 'y' in inp:
return True
if 'n' in inp:
return False
else:
return default == 'y'

View File

@ -1,38 +0,0 @@
'''
Onionr - Private P2P Communication
god log function
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import sys, time
from . import colors, raw, settings
colors = colors.Colors
def log(prefix, data, color = '', timestamp=True, fd = sys.stdout, prompt = True, terminal = False):
'''
Logs the data
prefix : The prefix to the output
data : The actual data to output
color : The color to output before the data
'''
curTime = ''
if timestamp:
curTime = time.strftime("%m-%d %H:%M:%S") + ' '
output = colors.reset + str(color) + ('[' + colors.bold + str(prefix) + colors.reset + str(color) + '] ' if prompt is True else '') + curTime + str(data) + colors.reset
if not settings.get_settings() & settings.USE_ANSI:
output = colors.filter(output)
raw.raw(output, fd = fd, terminal = terminal)

View File

@ -1,54 +0,0 @@
"""Onionr - Private P2P Communication.
Output raw data to file or terminal
"""
import sys
import os
from . import settings, colors
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
colors = colors.Colors
def raw(data, fd = sys.stdout, terminal = False):
"""
Outputs raw data to console without formatting
"""
if terminal and (settings.get_settings() & settings.OUTPUT_TO_CONSOLE):
try:
ts = fd.write('%s\n' % data)
except OSError:
pass
if settings.get_settings() & settings.OUTPUT_TO_FILE:
fdata = ''
try:
for _ in range(5):
try:
with open(settings._outputfile, 'r') as file:
fdata = file.read()
except UnicodeDecodeError:
pass
else:
break
except FileNotFoundError:
pass
fdata = fdata + '\n' + data
fdata = fdata.split('\n')
if len(fdata) >= settings.MAX_LOG_FILE_LINES:
fdata.pop(0)
fdata = '\n'.join(fdata)
with open(settings._outputfile, 'w') as file:
file.write(fdata)

View File

@ -1,37 +0,0 @@
'''
Onionr - Private P2P Communication
get a line of input from stdin
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import sys
from . import colors, settings
colors = colors.Colors
def readline(message = ''):
'''
Takes in input from the console, not stored in logs
message: The message to display before taking input
'''
color = colors.fg.green + colors.bold
output = colors.reset + str(color) + '... ' + colors.reset + str(message) + colors.reset
if not settings.get_settings() & settings.USE_ANSI:
output = colors.filter(output)
sys.stdout.write(output)
return input()

View File

@ -1,89 +0,0 @@
'''
Onionr - Private P2P Communication
logger settings
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import os
from utils import identifyhome
import filepaths
data_home = os.environ.get('ONIONR_LOG_DIR', identifyhome.identify_home())
# Use the bitwise operators to merge these settings
USE_ANSI = 0b100
if os.name == 'nt':
USE_ANSI = 0b000
OUTPUT_TO_CONSOLE = 0b010
OUTPUT_TO_FILE = 0b001
LEVEL_DEBUG = 1
LEVEL_INFO = 2
LEVEL_WARN = 3
LEVEL_ERROR = 4
LEVEL_FATAL = 5
LEVEL_IMPORTANT = 6
MAX_LOG_FILE_LINES = 10000
_type = OUTPUT_TO_CONSOLE | USE_ANSI # the default settings for logging
_level = LEVEL_DEBUG # the lowest level to log
# the file to log to
_outputfile = filepaths.log_file
def set_settings(type):
'''
Set the settings for the logger using bitwise operators
'''
global _type
_type = type
def get_settings():
'''
Get settings from the logger
'''
return _type
def set_level(level):
'''
Set the lowest log level to output
'''
global _level
_level = level
def get_level()->int:
'''
Get the lowest log level currently being outputted
'''
return _level
def set_file(outputfile):
'''
Set the file to output to, if enabled
'''
global _outputfile
_outputfile = outputfile
def get_file():
'''
Get the file to output to
'''
return _outputfile

View File

@ -8,20 +8,19 @@ import sys
import platform
import signal
from threading import Thread
from logger import log as logging
from logger import enable_file_logging
import filenuke
import psutil
import config
import logger
from onionrplugins import onionrevents as events
from utils import identifyhome
import filepaths
import onionrvalues
from onionrutils import cleanup
from onionrcrypto import getourkeypair
from onionrthreads import add_onionr_thread
from blockdb.blockcleaner import clean_block_database
from .. import version
@ -44,25 +43,39 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def _safe_remove(path):
try:
os.remove(path)
except FileNotFoundError:
pass
def delete_run_files():
"""Delete run files, do not error if not found.
Test: test_cleanup.py
"""
_safe_remove(filepaths.lock_file)
_safe_remove(filepaths.gossip_server_socket_file)
_safe_remove(filepaths.pid_file)
def _show_info_messages():
version.version(verbosity=5, function=logger.info)
logger.debug('Python version %s' % platform.python_version())
version.version(verbosity=5, function=logging.info)
logging.debug('Python version %s' % platform.python_version())
if onionrvalues.DEVELOPMENT_MODE:
logger.warn('Development mode enabled', timestamp=False, terminal=True)
logger.info('Using public key: %s' %
(logger.colors.underline +
getourkeypair.get_keypair()[0][:52]))
logging.warn('Development mode enabled')
def daemon():
"""Start Onionr's primary threads for communicator, API server, node, and LAN."""
if config.get('log.file.output', False):
enable_file_logging()
def _handle_sig_term(signum, frame):
sys.exit(0)
with open(filepaths.pid_file, 'w') as f:
f.write(str(os.getpid()))
@ -74,26 +87,30 @@ def daemon():
security_level = config.get('general.security_level', 1)
_show_info_messages()
logger.info(
f"Onionr daemon is running under pid {os.getpid()}", terminal=True)
logging.info(
f"Onionr daemon is running under pid {os.getpid()}")
events.event('init', threaded=False)
events.event('afterinit', threaded=False)
events.event('daemon_start')
add_onionr_thread(
clean_block_database, 60, 'clean_block_database', initial_sleep=0)
Thread(
target=gossip.start_gossip_threads,
daemon=True,
target=gossip.start_gossip_threads,
daemon=True,
name='start_gossip_threads').start()
try:
while True:
# Mainly for things like repls
events.event('primary_loop', threaded=False)
sleep(60)
except KeyboardInterrupt:
pass
cleanup.delete_run_files()
delete_run_files()
if security_level >= 2:
filenuke.nuke.clean_tree(identifyhome.identify_home())
@ -104,33 +121,25 @@ def start(override: bool = False):
Error exit if there is and its not overridden
"""
if os.path.exists(filepaths.lock_file) and not override:
if os.path.exists(filepaths.restarting_indicator):
try:
os.remove(filepaths.restarting_indicator)
except FileNotFoundError:
pass
else:
return
with open(filepaths.lock_file, 'r') as lock_file:
try:
proc = psutil.Process(int(lock_file.read())).name()
except psutil.NoSuchProcess:
proc = ""
if not proc.startswith("python"):
logger.warn(
f"Detected stale run file, deleting {filepaths.lock_file}",
terminal=True)
logging.warn(
f"Detected stale run file, deleting {filepaths.lock_file}")
try:
os.remove(filepaths.lock_file)
except FileNotFoundError:
pass
start(override=True)
return
logger.fatal('Cannot start. Daemon is already running,'
logging.error('Cannot start. Daemon is already running,'
+ ' or it did not exit cleanly.\n'
+ ' (if you are sure that there is not a daemon running,'
+ f' delete {filepaths.lock_file} & try again).',
terminal=True)
)
else:
if not onionrvalues.DEVELOPMENT_MODE:
lock_file = open(filepaths.lock_file, 'w')

View File

@ -1,24 +0,0 @@
"""Onionr - Private P2P Communication.
Open the web interface properly into a web browser, and return it
"""
import logger
from onionrutils import getclientapiserver
def get_url(config) -> str:
"""Build UI URL string and return it."""
onboarding = ""
if not config.get('onboarding.done', False):
onboarding = "onboarding/"
try:
url = getclientapiserver.get_client_API_server()
except FileNotFoundError:
url = ""
logger.error(
'Onionr seems to not be running (could not get api host)',
terminal=True)
else:
url = 'http://%s/%s#%s' % (url, onboarding, config.get('client.webpassword'))
logger.info('Onionr web interface URL: ' + url, terminal=True)
return url

View File

@ -6,7 +6,7 @@ import os
from signal import SIGTERM
from filepaths import pid_file
import logger
from logger import log as logging
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -29,9 +29,8 @@ def kill_daemon():
with open(pid_file, 'r') as pid:
os.kill(int(pid.read()), SIGTERM)
except FileNotFoundError:
logger.error("Daemon not running/pid file missing")
logger.warn('Stopping the running daemon, if one exists...', timestamp=False,
terminal=True)
logging.error("Daemon not running/pid file missing")
logging.warn('Stopping the running daemon, if one exists...')
kill_daemon.onionr_help = "Gracefully stops the " # type: ignore

View File

@ -5,11 +5,12 @@ Show nice logo
import os
import config
import logger
from .quotes import QUOTE
from utils.boxprint import bordered
from utils import logoheader
from utils import readstatic
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -25,28 +26,34 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def header():
if onionrvalues.DEVELOPMENT_MODE:
return
pink_ansi = '\033[95m'
green_ansi = '\033[92m'
reset_ansi = '\x1b[0m'
logo = readstatic.read_static('header.txt', ret_bin=False)
logo = logo.replace('P', pink_ansi).replace('G', green_ansi).replace('W', reset_ansi)
print(reset_ansi + logo)
def show_logo():
logger.raw('', terminal=True)
try:
terminal_size = os.get_terminal_size().columns
except OSError: # Generally thrown if not in terminal
terminal_size = 120
# print nice header thing :)
if config.get('general.display_header', True):
logoheader.header("")
header()
if terminal_size >= 120:
if QUOTE[1]: # If there is an author to show for the quote
logger.info(
"\u001b[33m\033[F" + bordered(QUOTE[0] + '\n -' + QUOTE[1]),
terminal=True)
print("\u001b[33m\033[F" + bordered(QUOTE[0] + '\n -' + QUOTE[1]))
else:
logger.info(
"\u001b[33m\033[F" + bordered(QUOTE[0]), terminal=True)
print("\u001b[33m\033[F" + bordered(QUOTE[0]))
else:
if QUOTE[1]:
logger.info("\u001b[33m\033[F" + QUOTE[0] + '\n -' + QUOTE[1],
terminal=True)
print("\u001b[33m\033[F" + QUOTE[0] + '\n -' + QUOTE[1])
else:
logger.info("\u001b[33m\033[F" + QUOTE[0], terminal=True)
print("\u001b[33m\033[F" + QUOTE[0])

View File

@ -1,146 +0,0 @@
"""Onionr - Private P2P Communication.
This module defines commands to show stats/details about the local node
"""
import os
import logger
from onionrutils import mnemonickeys
from utils import sizeutils, getconsolewidth, identifyhome
from coredb import keydb
import onionrcrypto
import config
import onionrvalues
from filepaths import lock_file
import psutil
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def _is_running():
script = onionrvalues.SCRIPT_NAME
if os.path.isfile(lock_file):
for process in psutil.process_iter():
if process.name() == script:
return True
return False
def show_stats():
"""Print/log statistic info about our Onionr install."""
try:
# define stats messages here
home = identifyhome.identify_home()
messages = {
# info about local client
# This line is inaccurate if dev mode is enabled
'Onionr Daemon Status':
((logger.colors.fg.green + 'Online') \
if _is_running() \
else logger.colors.fg.red + 'Offline'),
# file and folder size stats
'div1': True, # this creates a solid line across the screen, a div
'Total Block Size':
sizeutils.human_size(sizeutils.size(home + 'blocks.db')),
'Total Plugin Size':
sizeutils.human_size(sizeutils.size(home + 'plugins/')),
'Log File Size':
sizeutils.human_size(sizeutils.size(home + 'output.log')),
# count stats
'div2': True,
'Enabled Plugins':
str(len(config.get('plugins.enabled', list()))) + ' / ' +
str(len(os.listdir(home + 'plugins/')))
}
# color configuration
colors = {
'title': logger.colors.bold,
'key': logger.colors.fg.lightgreen,
'val': logger.colors.fg.green,
'border': logger.colors.fg.lightblue,
'reset': logger.colors.reset
}
# pre-processing
maxlength = 0
width = getconsolewidth.get_console_width()
for key, val in messages.items():
if not (type(val) is bool and val is True):
maxlength = max(len(key), maxlength)
prewidth = maxlength + len(' | ')
groupsize = width - prewidth - len('[+] ')
# generate stats table
logger.info(colors['title'] + 'Onionr v%s Statistics' %
onionrvalues.ONIONR_VERSION + colors['reset'],
terminal=True)
logger.info(colors['border'] + '-' * (maxlength + 1) +
'+' + colors['reset'], terminal=True)
for key, val in messages.items():
if not (type(val) is bool and val is True):
val = [str(val)[i:i + groupsize]
for i in range(0, len(str(val)), groupsize)]
logger.info(colors['key'] + str(key).rjust(maxlength) +
colors['reset'] + colors['border'] +
' | ' + colors['reset'] + colors['val'] +
str(val.pop(0)) + colors['reset'], terminal=True)
for value in val:
logger.info(' ' * maxlength + colors['border'] + ' | ' +
colors['reset'] + colors['val'] + str(
value) + colors['reset'], terminal=True)
else:
logger.info(colors['border'] + '-' * (maxlength +
1) + '+' +
colors['reset'], terminal=True)
logger.info(colors['border'] + '-' * (maxlength + 1) +
'+' + colors['reset'], terminal=True)
except Exception as e: # pylint: disable=W0703
logger.error('Failed to generate statistics table. ' +
str(e), error=e, timestamp=False, terminal=True)
def show_details():
"""Print out details.
node transport address(es)
active user ID
active user ID in mnemonic form
"""
details = {
'Data directory': identifyhome.identify_home(),
'Public Key': onionrcrypto.pub_key.replace('=', ''),
'Human-readable Public Key': mnemonickeys.get_human_readable_ID()
}
for detail in details:
logger.info('%s%s: \n%s%s\n' % (logger.colors.fg.lightgreen,
detail, logger.colors.fg.green,
details[detail]), terminal=True)
show_details.onionr_help = "Shows relevant information " # type: ignore
show_details.onionr_help += "for your Onionr install:"
show_stats.onionr_help = "Shows statistics for your Onionr " # type: ignore
show_stats.onionr_help += "node. Slow if Onionr is not running" # type: ignore

View File

@ -11,7 +11,7 @@ try:
except (KeyError, IndexError) as _:
pass
import logger
from logger import log as logging
import onionrexceptions
import onionrplugins
from onionrplugins import onionrpluginapi
@ -48,10 +48,6 @@ def register_plugin_commands(cmd) -> bool:
return False
def _show_term(msg: str):
logger.info(msg, terminal=True)
def register():
"""Register commands and handles help command processing."""
def get_help_message(cmd: str,
@ -80,7 +76,7 @@ def register():
try:
cmd = sys.argv[1]
except IndexError:
logger.info('Run with --help to see available commands', terminal=True)
logging.info('Run with --help to see available commands')
sys.exit(10)
is_help_cmd = False
@ -102,29 +98,28 @@ def register():
sys.argv[2]
except IndexError:
for i in arguments.get_arguments():
_show_term('%s <%s>: %s' % (PROGRAM_NAME, '/'.join(i),
logging.info('%s <%s>: %s' % (PROGRAM_NAME, '/'.join(i),
get_help_message(i[0])))
for pl in onionrplugins.get_enabled_plugins():
pl = onionrplugins.get_plugin(pl)
if hasattr(pl, 'ONIONR_COMMANDS'):
print('')
try:
_show_term('%s commands:' % (pl.plugin_name,))
logging.info('%s commands:' % (pl.plugin_name,))
except AttributeError:
_show_term('%s commands:' % (pl.__name__,))
logging.info('%s commands:' % (pl.__name__,))
for plugin_cmd in pl.ONIONR_COMMANDS:
_show_term('%s %s: %s' %
logging.info('%s %s: %s' %
(PROGRAM_NAME,
plugin_cmd,
get_help_message(plugin_cmd)),)
print('')
else:
try:
_show_term('%s %s: %s' % (PROGRAM_NAME,
logging.info('%s %s: %s' % (PROGRAM_NAME,
sys.argv[2],
get_help_message(sys.argv[2])))
except KeyError:
logger.error('%s: command does not exist.' % [sys.argv[2]],
terminal=True)
logging.error('%s: command does not exist.' % [sys.argv[2]])
sys.exit(3)
return

View File

@ -4,8 +4,7 @@ Sets CLI arguments for Onionr
"""
from typing import Callable
from .. import onionrstatistics, version, daemonlaunch
from .. import pubkeymanager # commands to add or change id
from .. import version, daemonlaunch
from .. import resetplugins # command to reinstall default plugins
@ -33,14 +32,10 @@ def get_arguments() -> dict:
dynamically modify them with plugins
"""
args = {
('details', 'info'): onionrstatistics.show_details,
('stats', 'statistics'): onionrstatistics.show_stats,
('version',): version.version,
('start', 'daemon'): daemonlaunch.start,
('stop', 'kill'): daemonlaunch.kill_daemon,
('addid', 'add-id'): pubkeymanager.add_ID,
('changeid', 'change-id'): pubkeymanager.change_ID,
('resetplugins', 'reset-plugins'): resetplugins.reset
('resetplugins', 'reset-plugins', 'updateplugins', 'update-plugins'): resetplugins.reset
}
return args

View File

@ -4,7 +4,7 @@ Try to provide recommendations for invalid Onionr commands
"""
import sys
from difflib import SequenceMatcher
import logger
from logger import log as logging
from . import arguments
"""
This program is free software: you can redistribute it and/or modify
@ -30,9 +30,9 @@ def recommend(print_default: bool = True):
for key in args.keys():
for word in key:
if SequenceMatcher(None, tried, word).ratio() >= 0.75:
logger.warn(f'{print_message} "{tried}", '
logging.warn(f'{print_message} "{tried}", '
+ f'did you mean "{word}"?',
terminal=True)
)
return
if print_default:
logger.error('%s "%s"' % (print_message, tried), terminal=True)
logging.error('%s "%s"' % (print_message, tried))

View File

@ -1,95 +0,0 @@
"""Onionr - Private P2P Communication.
This module defines user ID-related CLI commands
"""
import sys
import getpass
import unpaddedbase32
import niceware
import logger
import onionrexceptions
from onionrutils import stringvalidators, bytesconverter
import config
import keymanager
import onionrcrypto
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
DETERMINISTIC_REQUIREMENT = onionrvalues.PASSWORD_LENGTH
def add_ID():
"""Command to create a new user ID key pair."""
key_manager = keymanager.KeyManager()
pw = ""
try:
sys.argv[2] # pylint: disable=W0104
if not sys.argv[2].lower() == 'true':
raise ValueError
except (IndexError, ValueError):
newID = key_manager.addKey()[0]
else:
pw = "-".join(niceware.generate_passphrase(32))
newID, privKey = onionrcrypto.generate_deterministic(pw)
try:
key_manager.addKey(pubKey=newID,
privKey=privKey)
except ValueError:
logger.error(
'That ID is already available, you can change to it ' +
'with the change-id command.', terminal=True)
return
if pw:
print("Phrase to restore ID:", pw)
logger.info('Added ID: %s' %
(bytesconverter.bytes_to_str(newID.replace('=', '')),), terminal=True)
add_ID.onionr_help = "If the first argument is true, " # type: ignore
add_ID.onionr_help += "Onionr will show a deterministic " # type: ignore
add_ID.onionr_help += "generation prompt. Otherwise it will " # type: ignore
add_ID.onionr_help += "generate & save a new random key pair." # type: ignore
def change_ID():
"""Command to change active ID from argv or stdin."""
key_manager = keymanager.KeyManager()
try:
key = sys.argv[2]
key = unpaddedbase32.repad(key.encode()).decode()
except IndexError:
logger.warn('Specify pubkey to use', terminal=True)
else:
if stringvalidators.validate_pub_key(key):
key_list = key_manager.getPubkeyList()
if key in key_list or key.replace('=', '') in key_list:
config.set('general.public_key', key)
config.save()
logger.info('Set active key to: %s' % (key,), terminal=True)
logger.info('Restart Onionr if it is running.', terminal=True)
else:
logger.warn('That key does not exist', terminal=True)
else:
logger.warn('Invalid key %s' % (key,), terminal=True)
change_ID.onionr_help = "<pubkey>: Switches Onionr to " # type: ignore
change_ID.onionr_help += "use a different user ID key. " # type: ignore
change_ID.onionr_help += "You should immediately restart " # type: ignore
change_ID.onionr_help += "Onionr if it is running." # type: ignore

View File

@ -6,7 +6,7 @@ import os
import shutil
from utils import identifyhome
import logger
from logger import log as logging
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -32,7 +32,7 @@ def reset():
if os.path.exists(plugin_dir):
shutil.rmtree(plugin_dir)
logger.info('Default plugins have been reset.', terminal=True)
logging.info('Default plugins have been reset.')
reset.onionr_help = "reinstalls default Onionr plugins" # type: ignore

View File

@ -5,7 +5,7 @@ Command to show version info
import platform
from utils import identifyhome
import onionrvalues
import logger
from logger import log as logging
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -22,24 +22,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def version(verbosity=5, function=logger.info):
def version(verbosity=5, function=logging.info):
"""Display the Onionr version."""
function('Onionr v%s (%s) (API v%s)' % (onionrvalues.ONIONR_VERSION,
platform.machine(),
onionrvalues.API_VERSION),
terminal=True)
function('Onionr v%s (%s)' % (onionrvalues.ONIONR_VERSION,
platform.machine()))
if verbosity >= 1:
function(onionrvalues.ONIONR_TAGLINE, terminal=True)
function(onionrvalues.ONIONR_TAGLINE)
if verbosity >= 2:
pf = platform.platform()
release = platform.release()
python_imp = platform.python_implementation()
python_version = platform.python_version()
function(
f'{python_imp} {python_version} on {pf} {release}',
terminal=True)
f'{python_imp} {python_version} on {pf} {release}')
function('Onionr data dir: %s' %
identifyhome.identify_home(), terminal=True)
identifyhome.identify_home())
version.onionr_help = 'Shows environment details including ' # type: ignore

View File

@ -1,27 +0,0 @@
'''
Onionr - Private P2P Communication
This file handles Onionr's cryptography.
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
from . import generate, hashers, getourkeypair, signing, encryption, cryptoutils
generate_deterministic = generate.generate_deterministic
generate = generate.generate_pub_key
keypair = getourkeypair.get_keypair()
pub_key = keypair[0]
priv_key = keypair[1]

View File

@ -1,6 +0,0 @@
from . import safecompare, replayvalidation
from . import getpubfrompriv
replay_validator = replayvalidation.replay_timestamp_validation
safe_compare = safecompare.safe_compare
get_pub_key_from_priv = getpubfrompriv.get_pub_key_from_priv

View File

@ -1,28 +0,0 @@
"""Onionr - Private P2P Communication.
generate a public ed25519 key from a private one
"""
from nacl import signing, encoding
from onionrtypes import UserID, UserIDSecretKey
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def get_pub_key_from_priv(priv_key: UserIDSecretKey,
raw_encoding: bool = False) -> UserID:
return signing.SigningKey(
priv_key, encoder=encoding.Base32Encoder).verify_key.encode(
encoding.Base32Encoder)

View File

@ -1,3 +0,0 @@
from onionrutils import epoch
def replay_timestamp_validation(timestamp):
return epoch.get_epoch() - int(timestamp) <= 2419200

View File

@ -1,12 +0,0 @@
import hmac
def safe_compare(one, two):
# Do encode here to avoid spawning core
try:
one = one.encode()
except AttributeError:
pass
try:
two = two.encode()
except AttributeError:
pass
return hmac.compare_digest(one, two)

View File

@ -1,38 +0,0 @@
from .. import hashers
import config, onionrproofs, logger
import onionrexceptions
def verify_POW(blockContent):
'''
Verifies the proof of work associated with a block
'''
retData = False
dataLen = len(blockContent)
try:
blockContent = blockContent.encode()
except AttributeError:
pass
blockHash = hashers.sha3_hash(blockContent)
try:
blockHash = blockHash.decode() # bytes on some versions for some reason
except AttributeError:
pass
difficulty = onionrproofs.getDifficultyForNewBlock(blockContent)
if difficulty < int(config.get('general.minimum_block_pow')):
difficulty = int(config.get('general.minimum_block_pow'))
mainHash = '0000000000000000000000000000000000000000000000000000000000000000'#nacl.hash.blake2b(nacl.utils.random()).decode()
puzzle = mainHash[:difficulty]
if blockHash[:difficulty] == puzzle:
# logger.debug('Validated block pow')
retData = True
else:
logger.debug(f"Invalid token, bad proof for {blockHash} {puzzle}")
raise onionrexceptions.InvalidProof('Proof for %s needs to be %s' % (blockHash, puzzle))
return retData

View File

@ -1,47 +0,0 @@
import nacl.encoding, nacl.public, nacl.signing
from .. import getourkeypair
import unpaddedbase32
from onionrutils import bytesconverter, stringvalidators
pair = getourkeypair.get_keypair()
our_pub_key = unpaddedbase32.repad(pair[0].encode())
our_priv_key = unpaddedbase32.repad(pair[1].encode())
def pub_key_encrypt(data, pubkey, encodedData=False):
'''Encrypt to a public key (Curve25519, taken from base32 Ed25519 pubkey)'''
pubkey = unpaddedbase32.repad(bytesconverter.str_to_bytes(pubkey))
retVal = ''
box = None
data = bytesconverter.str_to_bytes(data)
pubkey = nacl.signing.VerifyKey(pubkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_public_key()
if encodedData:
encoding = nacl.encoding.Base64Encoder
else:
encoding = nacl.encoding.RawEncoder
box = nacl.public.SealedBox(pubkey)
retVal = box.encrypt(data, encoder=encoding)
return retVal
def pub_key_decrypt(data, pubkey='', privkey='', encodedData=False):
'''pubkey decrypt (Curve25519, taken from Ed25519 pubkey)'''
if pubkey != '':
pubkey = unpaddedbase32.repad(bytesconverter.str_to_bytes(pubkey))
decrypted = False
if encodedData:
encoding = nacl.encoding.Base64Encoder
else:
encoding = nacl.encoding.RawEncoder
if privkey == '':
privkey = our_priv_key
ownKey = nacl.signing.SigningKey(seed=privkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_private_key()
if stringvalidators.validate_pub_key(privkey):
privkey = nacl.signing.SigningKey(seed=privkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_private_key()
anonBox = nacl.public.SealedBox(privkey)
else:
anonBox = nacl.public.SealedBox(ownKey)
decrypted = anonBox.decrypt(data, encoder=encoding)
return decrypted

View File

@ -1,65 +0,0 @@
"""Onionr - Private P2P Communication.
functions to generate ed25519 key pairs
"""
import nacl.signing
import nacl.encoding
import nacl.pwhash
import onionrexceptions
from onionrutils import bytesconverter
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def generate_pub_key():
"""Generate a Ed25519 public key pair.
return tuple of base32encoded pubkey, privkey
"""
private_key = nacl.signing.SigningKey.generate()
public_key = private_key.verify_key.encode(
encoder=nacl.encoding.Base32Encoder())
return (public_key.decode(), private_key.encode(
encoder=nacl.encoding.Base32Encoder()).decode())
def generate_deterministic(passphrase, bypassCheck=False):
"""Generate a Ed25519 public key pair from a phase.
not intended for human-generated key
"""
passStrength = onionrvalues.PASSWORD_LENGTH
# Convert to bytes if not already
passphrase = bytesconverter.str_to_bytes(passphrase)
# Validate passphrase length
if not bypassCheck:
if len(passphrase) < passStrength:
raise onionrexceptions.PasswordStrengthError(
"Passphase must be at least %s characters" % (passStrength,))
# KDF values
kdf = nacl.pwhash.argon2id.kdf
# Does not need to be secret, but must be 16 bytes
salt = b"U81Q7llrQcdTP0Ux"
ops = nacl.pwhash.argon2id.OPSLIMIT_SENSITIVE
mem = nacl.pwhash.argon2id.MEMLIMIT_SENSITIVE
# Generate seed for ed25519 key
key = kdf(32, passphrase, salt, opslimit=ops, memlimit=mem)
key = nacl.signing.SigningKey(key)
return (
key.verify_key.encode(nacl.encoding.Base32Encoder).decode(),
key.encode(nacl.encoding.Base32Encoder).decode())

View File

@ -1,36 +0,0 @@
"""
Onionr - Private P2P Communication
returns our current active keypair
"""
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import keymanager, config, filepaths
from . import generate
def get_keypair():
key_m = keymanager.KeyManager()
if os.path.exists(filepaths.keys_file):
if len(config.get('general.public_key', '')) > 0:
pubKey = config.get('general.public_key')
else:
pubKey = key_m.getPubkeyList()[0]
privKey = key_m.getPrivkey(pubKey)
else:
keys = generate.generate_pub_key()
pubKey = keys[0]
privKey = keys[1]
key_m.addKey(pubKey, privKey)
return (pubKey, privKey)

View File

@ -1,21 +0,0 @@
import hashlib
import nacl.hash
def sha3_hash(data):
try:
data = data.encode()
except AttributeError:
pass
hasher = hashlib.sha3_256()
hasher.update(data)
return hasher.hexdigest()
def blake2b_hash(data):
try:
data = data.encode()
except AttributeError:
pass
return nacl.hash.blake2b(data)

View File

@ -1,45 +0,0 @@
import base64, binascii
import unpaddedbase32
import nacl.encoding, nacl.signing, nacl.exceptions
from onionrutils import bytesconverter
from onionrutils import mnemonickeys
import logger
def ed_sign(data, key, encodeResult=False):
'''Ed25519 sign data'''
key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key))
try:
data = data.encode()
except AttributeError:
pass
key = nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder)
retData = ''
if encodeResult:
retData = key.sign(data, encoder=nacl.encoding.Base64Encoder).signature.decode() # .encode() is not the same as nacl.encoding
else:
retData = key.sign(data).signature
return retData
def ed_verify(data, key, sig, encodedData=True):
'''Verify signed data (combined in nacl) to an ed25519 key'''
key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key))
try:
key = nacl.signing.VerifyKey(key=key, encoder=nacl.encoding.Base32Encoder)
except nacl.exceptions.ValueError:
return False
except binascii.Error:
logger.warn('Could not load key for verification, invalid padding')
return False
retData = False
sig = base64.b64decode(sig)
try:
data = data.encode()
except AttributeError:
pass
try:
retData = key.verify(data, sig) # .encode() is not the same as nacl.encoding
except nacl.exceptions.BadSignatureError:
pass
return retData

View File

@ -17,11 +17,13 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os, re, importlib
import os, re
import importlib.util
import traceback
from . import onionrevents as events
import config, logger
from .pluginapis import plugin_apis
import config, logging
from utils import identifyhome
# set data dir
@ -42,9 +44,9 @@ def reload(stop_event = True):
enabled_plugins = get_enabled_plugins()
if stop_event is True:
logger.debug('Reloading all plugins...')
logging.debug('Reloading all plugins...')
else:
logger.debug('Loading all plugins...')
logging.debug('Loading all plugins...')
if stop_event is True:
for plugin in enabled_plugins:
@ -55,7 +57,7 @@ def reload(stop_event = True):
return True
except:
logger.error('Failed to reload plugins.')
logging.error('Failed to reload plugins.')
return False
@ -72,8 +74,8 @@ def enable(name, start_event = True):
except ImportError as e: # Was getting import error on Gitlab CI test "data"
# NOTE: If you are experiencing issues with plugins not being enabled, it might be this resulting from an error in the module
# can happen inconsistently (especially between versions)
logger.error('Failed to enable module:', terminal=True)
logger.error(traceback.format_exc(), terminal=True)
logging.error('Failed to enable module:')
logging.error(traceback.format_exc())
return False
else:
enabled_plugins.append(name)
@ -85,8 +87,8 @@ def enable(name, start_event = True):
else:
return False
else:
logger.error('Failed to enable plugin \"%s\", disabling plugin.' % name, terminal=True)
logger.debug('Plugins folder not found: %s' % get_plugins_folder(str(name).lower()), terminal=True)
logging.error('Failed to enable plugin \"%s\", disabling plugin.' % name)
logging.debug('Plugins folder not found: %s' % get_plugins_folder(str(name).lower()))
disable(name)
return False
@ -128,9 +130,9 @@ def start(name):
return plugin
except:
logger.error('Failed to start module \"%s\".' % name)
logging.error('Failed to start module \"%s\".' % name)
else:
logger.error('Failed to start nonexistant module \"%s\".' % name)
logging.error('Failed to start nonexistant module \"%s\".' % name)
return None
@ -152,9 +154,9 @@ def stop(name):
return plugin
except:
logger.error('Failed to stop module \"%s\".' % name)
logging.error('Failed to stop module \"%s\".' % name)
else:
logger.error('Failed to stop nonexistant module \"%s\".' % name)
logging.error('Failed to stop nonexistant module \"%s\".' % name)
return None
@ -257,11 +259,11 @@ def check():
"""
if not config.is_set('plugins'):
logger.debug('Generating plugin configuration data...')
logging.debug('Generating plugin configuration data...')
config.set('plugins', {'enabled': []}, True)
if not os.path.exists(os.path.dirname(get_plugins_folder())):
logger.debug('Generating plugin data folder...')
logging.debug('Generating plugin data folder...')
try:
os.makedirs(os.path.dirname(get_plugins_folder()))
except FileExistsError:

View File

@ -7,7 +7,7 @@ from threading import Thread
import traceback
import config, logger
import config, logging
import onionrplugins as plugins
from . import onionrpluginapi as pluginapi
"""
@ -41,11 +41,11 @@ def __event_caller(event_name, data = {}):
try:
call(plugins.get_plugin(plugin), event_name, data, get_pluginapi(data))
except ModuleNotFoundError as _:
logger.warn('Disabling nonexistant plugin "%s"...' % plugin, terminal=True)
logging.warn('Disabling nonexistant plugin "%s"...' % plugin)
plugins.disable(plugin, stop_event = False)
except Exception as _:
logger.error('Event "%s" failed for plugin "%s".' % (event_name, plugin), terminal=True)
logger.error('\n' + traceback.format_exc(), terminal=True)
logging.error('Event "%s" failed for plugin "%s".' % (event_name, plugin))
logging.error('\n' + traceback.format_exc())
def event(event_name, data = {}, threaded = True):
"""Call an event on all plugins (if defined)"""

View File

@ -18,7 +18,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import onionrplugins, logger
import onionrplugins, logging
class PluginAPI:

View File

@ -0,0 +1,7 @@
#
from typing import Callable, Dict
# plugin apis are methods intended to be available to the rpc
# plugin, this is so plugins can provide apis to other plugins
# plugins add their methods during or before afterinit event
plugin_apis: Dict[str, Callable] = {}

View File

@ -1,120 +0,0 @@
"""Onionr - Private P2P Communication.
DBCreator, creates sqlite3 databases used by Onionr
"""
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import sqlite3, os
from coredb import dbfiles
import filepaths
def createAddressDB():
'''
Generate the address database
types:
1: I2P b32 address
2: Tor v2 (like facebookcorewwwi.onion)
3: Tor v3
'''
if os.path.exists(dbfiles.address_info_db):
raise FileExistsError("Address database already exists")
conn = sqlite3.connect(dbfiles.address_info_db)
c = conn.cursor()
c.execute('''CREATE TABLE adders(
address text,
type int,
knownPeer text,
speed int,
success int,
powValue text,
failure int,
lastConnect int,
lastConnectAttempt int,
trust int,
introduced int
);
''')
conn.commit()
conn.close()
def createPeerDB():
'''
Generate the peer sqlite3 database and populate it with the peers table.
'''
if os.path.exists(dbfiles.user_id_info_db):
raise FileExistsError("User database already exists")
# generate the peer database
conn = sqlite3.connect(dbfiles.user_id_info_db)
c = conn.cursor()
c.execute('''CREATE TABLE peers(
ID text not null,
name text,
adders text,
dateSeen not null,
trust int,
hashID text);
''')
c.execute('''CREATE TABLE forwardKeys(
peerKey text not null,
forwardKey text not null,
date int not null,
expire int not null
);''')
conn.commit()
conn.close()
return
def createForwardKeyDB():
'''
Create the forward secrecy key db (*for *OUR* keys*)
'''
if os.path.exists(dbfiles.forward_keys_db):
raise FileExistsError("Block database already exists")
conn = sqlite3.connect(dbfiles.forward_keys_db)
c = conn.cursor()
c.execute('''CREATE TABLE myForwardKeys(
peer text not null,
publickey text not null,
privatekey text not null,
date int not null,
expire int not null
);
''')
conn.commit()
conn.close()
return
def create_blacklist_db():
if os.path.exists(dbfiles.blacklist_db):
raise FileExistsError("Blacklist db already exists")
conn = sqlite3.connect(dbfiles.blacklist_db, timeout=10)
c = conn.cursor()
# Create table
c.execute('''CREATE TABLE blacklist(
hash text primary key not null,
dataType int,
blacklistDate int,
expire int
);
''')
conn.commit()
conn.close()
create_funcs = [createAddressDB, createPeerDB,
createForwardKeyDB, create_blacklist_db]

View File

@ -20,16 +20,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import os, shutil
import onionrplugins as plugins
import logger
from logger import log as logging
import filepaths
from utils.readstatic import get_static_dir
def setup_default_plugins():
# Copy default plugins into plugins folder
if os.path.exists(get_static_dir() + '/default-plugins/'):
names = [f for f in os.listdir(get_static_dir() + '/default-plugins/')]
if os.path.exists(get_static_dir() + '/official-plugins/'):
names = [f for f in os.listdir(get_static_dir() + '/official-plugins/')]
shutil.copytree(
get_static_dir() + '/default-plugins/',
get_static_dir() + '/official-plugins/',
plugins.get_plugins_folder(), dirs_exist_ok=True)
@ -38,9 +38,9 @@ def setup_default_plugins():
if not name in plugins.get_enabled_plugins():
plugins.enable(name)
else:
logger.error(
logging.error(
"Plugin source directory does not exist!" +
"Onionr needs plugins to be useful", terminal=True)
"Onionr needs plugins to be useful")
for name in plugins.get_enabled_plugins():
@ -50,5 +50,5 @@ def setup_default_plugins():
except FileExistsError:
pass
except Exception as e:
#logger.warn('Error enabling plugin: ' + str(e), terminal=True)
#logging.warn('Error enabling plugin: ' + str(e))
plugins.disable(name, stop_event = False)

View File

@ -8,9 +8,8 @@ import base64
import ujson as json
import config
import logger
from logger import log as logging
import onionrvalues
from logger.settings import *
from utils import readstatic
"""
This program is free software: you can redistribute it and/or modify
@ -37,42 +36,3 @@ def setup_config():
config.save()
config.reload()
settings = 0b000
if config.get('log.console.color', True):
settings = settings | USE_ANSI
if config.get('log.console.output', True):
settings = settings | OUTPUT_TO_CONSOLE
if config.get('log.file.output', True):
settings = settings | OUTPUT_TO_FILE
set_settings(settings)
verbosity = str(config.get('log.verbosity', 'default')).lower().strip()
if not verbosity in ['default', 'null', 'none', 'nil']:
map = {
str(LEVEL_DEBUG) : LEVEL_DEBUG,
'verbose' : LEVEL_DEBUG,
'debug' : LEVEL_DEBUG,
str(LEVEL_INFO) : LEVEL_INFO,
'info' : LEVEL_INFO,
'information' : LEVEL_INFO,
str(LEVEL_WARN) : LEVEL_WARN,
'warn' : LEVEL_WARN,
'warning' : LEVEL_WARN,
'warnings' : LEVEL_WARN,
str(LEVEL_ERROR) : LEVEL_ERROR,
'err' : LEVEL_ERROR,
'error' : LEVEL_ERROR,
'errors' : LEVEL_ERROR,
str(LEVEL_FATAL) : LEVEL_FATAL,
'fatal' : LEVEL_FATAL,
str(LEVEL_IMPORTANT) : LEVEL_IMPORTANT,
'silent' : LEVEL_IMPORTANT,
'quiet' : LEVEL_IMPORTANT,
'important' : LEVEL_IMPORTANT
}
if verbosity in map:
set_level(map[verbosity])
else:
logger.warn('Verbosity level %s is not valid, using default verbosity.' % verbosity)

View File

@ -6,7 +6,7 @@ from threading import Thread
from uuid import uuid4
from time import sleep
import logger
from logger import log as logging
def _onionr_thread(func: Callable,
@ -18,10 +18,10 @@ def _onionr_thread(func: Callable,
try:
func(*args, **kwargs)
except Exception as _: # noqa
logger.warn(
logging.warn(
f"Onionr thread exception in {thread_id} \n" +
traceback.format_exc(),
terminal=True)
)
sleep(sleep_secs)

View File

@ -1,22 +0,0 @@
from typing import NewType
UserID = NewType('UserID', str)
UserIDSecretKey = NewType('UserIDSecretKey', str)
LoopBackIP = NewType('LoopBackIP', str)
DeterministicKeyPassphrase = NewType('DeterministicKeyPassphrase', str)
Ed25519PublicKeyBytes = NewType('Ed25519PublicKeyBytes', bytes)
BlockHash = NewType('BlockHash', str)
OnboardingConfig = NewType('OnboardingConfig', str)
# JSON serializable string. e.g. no raw bytes
JSONSerializable = NewType('JSONSerializable', str)
# Return value of some functions or methods, denoting operation success
# Do not use for new code
BooleanSuccessState = NewType('BooleanSuccessState', bool)

View File

@ -1,9 +0,0 @@
# onionrusers
onionrusers is a small collection of classes for interacting with onionr public keys, such as encrypting messages to them with forward secrecy, interacting with their settings, or else.
## Files
onionrusers.py: OnionrUsers class can be used to encrypt/decrypt messages to a particular Onionr user (incl. forward secrecy), view information about them, and get our friend list.
contactmanager.py: Inheriting from OnionrUsers, ContactManager allows arbitrary information to be associated with an Onionr user.

View File

@ -1,89 +0,0 @@
"""Onionr - Private P2P Communication.
Set more abstract information related to a peer.
Can be thought of as traditional 'contact' system
"""
import os
import ujson as json
import unpaddedbase32
import onionrexceptions
from onionrusers import onionrusers
from onionrutils import bytesconverter, epoch
from utils import identifyhome
from onionrutils import mnemonickeys
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
class ContactManager(onionrusers.OnionrUser):
def __init__(self, publicKey, saveUser=False, recordExpireSeconds=5):
try:
if mnemonickeys.DELIMITER in publicKey:
publicKey = mnemonickeys.get_base32(publicKey)
#publicKey = unpaddedbase32.b32encode(bytesconverter.str_to_bytes(publicKey))
except ValueError:
pass
publicKey = bytesconverter.bytes_to_str(unpaddedbase32.repad(bytesconverter.str_to_bytes(publicKey)))
super(ContactManager, self).__init__(publicKey, saveUser=saveUser)
home = identifyhome.identify_home()
self.dataDir = home + '/contacts/'
self.dataFile = '%s/contacts/%s.json' % (home, publicKey)
self.lastRead = 0
self.recordExpire = recordExpireSeconds
self.data = self._loadData()
self.deleted = False
if not os.path.exists(self.dataDir):
os.mkdir(self.dataDir)
def _writeData(self):
data = json.dumps(self.data)
with open(self.dataFile, 'w') as dataFile:
dataFile.write(data)
def _loadData(self):
self.lastRead = epoch.get_epoch()
retData = {}
if os.path.exists(self.dataFile):
with open(self.dataFile, 'r') as dataFile:
retData = json.loads(dataFile.read())
return retData
def set_info(self, key, value, autoWrite=True):
if self.deleted:
raise onionrexceptions.ContactDeleted
self.data[key] = value
if autoWrite:
self._writeData()
return
def get_info(self, key, forceReload=False):
if self.deleted:
raise onionrexceptions.ContactDeleted
if (epoch.get_epoch() - self.lastRead >= self.recordExpire) or forceReload:
self.data = self._loadData()
try:
return self.data[key]
except KeyError:
return None
def delete_contact(self):
self.deleted = True
if os.path.exists(self.dataFile):
os.remove(self.dataFile)

View File

@ -1,259 +0,0 @@
"""Onionr - Private P2P Communication.
Contains abstractions for interacting with users of Onionr
"""
import sqlite3
import time
import onionrexceptions
from onionrutils import stringvalidators, bytesconverter, epoch
import unpaddedbase32
import nacl.exceptions
from coredb import keydb, dbfiles
import onionrcrypto
from onionrcrypto import getourkeypair
from onionrvalues import DATABASE_LOCK_TIMEOUT
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def deleteExpiredKeys():
# Fetch the keys we generated for the peer, that are still around
conn = sqlite3.connect(
dbfiles.forward_keys_db, timeout=DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
curTime = epoch.get_epoch()
c.execute("DELETE from myForwardKeys where expire <= ?", (curTime,))
conn.commit()
conn.execute("VACUUM")
conn.close()
return
def deleteTheirExpiredKeys(pubkey):
conn = sqlite3.connect(
dbfiles.user_id_info_db, timeout=DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
# Prepare the insert
command = (pubkey, epoch.get_epoch())
c.execute("DELETE from forwardKeys where peerKey = ? and expire <= ?", command)
conn.commit()
conn.close()
DEFAULT_KEY_EXPIRE = 604800
class OnionrUser:
def __init__(self, publicKey, saveUser=False):
"""
OnionrUser is an abstraction for "users" of the network.
Takes a base32 encoded ed25519 public key, and a bool saveUser
saveUser determines if we should add a user to our peer database or not.
"""
publicKey = unpaddedbase32.repad(
bytesconverter.str_to_bytes(publicKey)).decode()
self.trust = 0
self.publicKey = publicKey
if saveUser and not publicKey == getourkeypair.get_keypair():
try:
keydb.addkeys.add_pub_key(publicKey)
except (AssertionError, ValueError) as _:
pass
self.trust = keydb.userinfo.get_user_info(self.publicKey, 'trust')
return
def setTrust(self, newTrust):
"""Set the peers trust. 0 = not trusted, 1 = friend, 2 = ultimate"""
keydb.userinfo.set_user_info(self.publicKey, 'trust', newTrust)
def isFriend(self):
if keydb.userinfo.get_user_info(self.publicKey, 'trust') == 1:
return True
return False
def getName(self):
retData = 'anonymous'
name = keydb.userinfo.get_user_info(self.publicKey, 'name')
try:
if len(name) > 0:
retData = name
except ValueError:
pass
return retData
def encrypt(self, data):
encrypted = onionrcrypto.encryption.pub_key_encrypt(
data, self.publicKey, encodedData=True)
return encrypted
def decrypt(self, data):
decrypted = onionrcrypto.encryption.pub_key_decrypt(
data, self.publicKey, encodedData=True)
return decrypted
def forwardEncrypt(self, data):
deleteTheirExpiredKeys(self.publicKey)
deleteExpiredKeys()
retData = ''
forwardKey = self._getLatestForwardKey()
if stringvalidators.validate_pub_key(forwardKey[0]):
retData = onionrcrypto.encryption.pub_key_encrypt(
data, forwardKey[0], encodedData=True)
else:
raise onionrexceptions.InvalidPubkey(
"No valid forward secrecy key available for this user")
return (retData, forwardKey[0], forwardKey[1])
def forwardDecrypt(self, encrypted):
retData = ""
for key in self.getGeneratedForwardKeys(False):
try:
retData = onionrcrypto.encryption.pub_key_decrypt(
encrypted, privkey=key[1], encodedData=True)
except nacl.exceptions.CryptoError:
retData = False
else:
break
else:
raise onionrexceptions.DecryptionError(
"Could not decrypt forward secrecy content")
return retData
def _getLatestForwardKey(self):
# Get the latest forward secrecy key for a peer
key = ""
conn = sqlite3.connect(
dbfiles.user_id_info_db, timeout=DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
# TODO: account for keys created at the same time (same epoch)
for row in c.execute(
"SELECT forwardKey, max(EXPIRE) FROM forwardKeys WHERE peerKey = ? ORDER BY expire DESC", # noqa
(self.publicKey,)):
key = (row[0], row[1])
break
conn.commit()
conn.close()
return key
def _getForwardKeys(self):
conn = sqlite3.connect(
dbfiles.user_id_info_db, timeout=DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
keyList = []
for row in c.execute(
"SELECT forwardKey, date FROM forwardKeys WHERE peerKey = ? ORDER BY expire DESC", # noqa
(self.publicKey,)):
keyList.append((row[0], row[1]))
conn.commit()
conn.close()
return list(keyList)
def generateForwardKey(self, expire=DEFAULT_KEY_EXPIRE):
# Generate a forward secrecy key for the peer
conn = sqlite3.connect(
dbfiles.forward_keys_db, timeout=DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
# Prepare the insert
time = epoch.get_epoch()
newKeys = onionrcrypto.generate()
newPub = bytesconverter.bytes_to_str(newKeys[0])
newPriv = bytesconverter.bytes_to_str(newKeys[1])
command = (self.publicKey, newPub, newPriv, time, expire + time)
c.execute("INSERT INTO myForwardKeys VALUES(?, ?, ?, ?, ?);", command)
conn.commit()
conn.close()
return newPub
def getGeneratedForwardKeys(self, genNew=True):
# Fetch the keys we generated for the peer, that are still around
conn = sqlite3.connect(
dbfiles.forward_keys_db, timeout=DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
pubkey = self.publicKey
pubkey = bytesconverter.bytes_to_str(pubkey)
command = (pubkey,)
keyList = [] # list of tuples containing pub, private for peer
for result in c.execute(
"SELECT * FROM myForwardKeys WHERE peer = ?", command):
keyList.append((result[1], result[2]))
if len(keyList) == 0:
if genNew:
self.generateForwardKey()
keyList = self.getGeneratedForwardKeys()
return list(keyList)
def addForwardKey(self, newKey, expire=DEFAULT_KEY_EXPIRE):
newKey = bytesconverter.bytes_to_str(
unpaddedbase32.repad(bytesconverter.str_to_bytes(newKey)))
if not stringvalidators.validate_pub_key(newKey):
# Do not add if something went wrong with the key
raise onionrexceptions.InvalidPubkey(newKey)
conn = sqlite3.connect(
dbfiles.user_id_info_db, timeout=DATABASE_LOCK_TIMEOUT)
c = conn.cursor()
# Get the time we're inserting the key at
timeInsert = epoch.get_epoch()
# Look at our current keys for duplicate key data or time
for entry in self._getForwardKeys():
if entry[0] == newKey:
return False
if entry[1] == timeInsert:
timeInsert += 1
# Sleep if our time is the same to prevent dupe time records
time.sleep(1)
# Add a forward secrecy key for the peer
# Prepare the insert
command = (self.publicKey, newKey, timeInsert, timeInsert + expire)
c.execute("INSERT INTO forwardKeys VALUES(?, ?, ?, ?);", command)
conn.commit()
conn.close()
return True
@classmethod
def list_friends(cls):
friendList = []
for x in keydb.listkeys.list_pub_keys(trust=1):
friendList.append(cls(x))
return list(friendList)

View File

@ -1,16 +0,0 @@
def str_to_bytes(data: str) -> bytes:
'''Convert a string to bytes with .encode(), utf8'''
try:
data = data.encode('UTF-8')
except AttributeError:
pass
return data
def bytes_to_str(data: bytes) -> str:
"""Convert bytes to strings with .decode(), utf8"""
try:
data = data.decode('UTF-8')
except AttributeError:
pass
return data

View File

@ -1,41 +0,0 @@
"""Onionr - Private P2P Communication.
cleanup run files
"""
import os
import filepaths
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def _safe_remove(path):
try:
os.remove(path)
except FileNotFoundError:
pass
def delete_run_files():
"""Delete run files, do not error if not found.
Test: test_cleanup.py
"""
_safe_remove(filepaths.public_API_host_file)
_safe_remove(filepaths.private_API_host_file)
_safe_remove(filepaths.daemon_mark_file)
_safe_remove(filepaths.lock_file)
_safe_remove(filepaths.gossip_server_socket_file)
_safe_remove(filepaths.pid_file)

View File

@ -1,31 +0,0 @@
"""Onionr - Private P2P Communication.
Get floored epoch, or rounded epoch
"""
import time
import math
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def get_rounded_epoch(roundS=60) -> int:
"""Return the epoch, rounded down to given seconds (Default 60)."""
epoch = get_epoch()
return epoch - (epoch % roundS)
def get_epoch() -> int:
"""return epoch"""
return math.floor(time.time())

Some files were not shown because too many files have changed in this diff Show More