index.md completed

This commit is contained in:
blurHY 2018-12-11 18:20:42 +08:00
parent 604b9bdfdb
commit 62d71fa271
16 changed files with 3571 additions and 0 deletions

257
docs/zh/faq.md Normal file
View File

@ -0,0 +1,257 @@
# Frequently asked questions
#### Do I need to have a port opened?
This is __optional__, you can browse and use ZeroNet sites without an open port.
If you want to create a new site it's highly recommended to have an open port.
At startup ZeroNet tries to open a port for you on your router using
[UPnP](https://wikipedia.org/wiki/Universal_Plug_and_Play), if this fails you have to do it manually:
- Try to access your router's web interface using [http://192.168.1.1](http://192.168.1.1)
or [http://192.168.0.1](http://192.168.0.1)
- Look for an "Enable UPnP support" or similar option then restart ZeroNet.
If it still doesn't work then try to find a 'port forwarding' section of your router page. This is different for every router. [Here is a tutorial on YouTube.](https://www.youtube.com/watch?v=aQXJ7sLSz14) The port to forward is 15441.
---
#### Is ZeroNet anonymous?
It's no more anonymous than BitTorrent, but privacy (the possibility to find out who is the owner of the comment/site) will increase as the network and the sites gains more peers.
ZeroNet is made to work with anonymity networks: you can easily hide your IP using the Tor network.
---
#### How to use ZeroNet with the Tor browser?
In Tor mode it is recommended to use ZeroNet from within the Tor Browser:
- Start the Tor Browser
- Go to address `about:preferences#advanced`
- Click `Settings...`
- Enter `127.0.0.1` to field **No proxy for**
- Open http://127.0.0.1:43110 in the browser
If you still see a blank page:
- Click on NoScript's button (first on the toolbar)
- Choose "Temporary allow all this page"
- Reload the page
---
#### How to use ZeroNet with Tor?
If you want to hide your IP address, install the latest version of ZeroNet then click Tor > Enable Tor for every connection on ZeroHello.
On Windows, Tor is bundled with ZeroNet. ZeroNet will attempt to download and unpack Tor on its first run. If this fails for any reason, you can install it manually following the instruction in `core\tools\tor\manual_install.txt`.
For other OS's, follow the instructions in the "How to make ZeroNet work with Tor under Linux/MacOS" section.
> __Tip:__ You can verify your IP address using ZeroNet's [Stats](http://127.0.0.1:43110/Stats) page.
> __Tip:__ If you get connection errors, make sure you have the latest version of Tor installed. (0.2.7.5+ required)
---
#### How to make ZeroNet work with Tor under Linux/MacOS?
- Install Tor for your OS following Tor's official guidelines: [Linux](https://www.torproject.org/download/download-unix.html.en) [Mac](https://www.torproject.org/docs/tor-doc-osx.html.en).
- `sudo nano /etc/tor/torrc`
- Remove the `#` character from lines `ControlPort 9051` and `CookieAuthentication 1` (line ~57)
- Restart tor
- Add permission for yourself to read the auth cookie. With Debian Linux, the command is `sudo usermod -a -G debian-tor [yourlinuxuser]`<br>(if you are not on Debian check the file's user group by `ls -al /var/run/tor/control.authcookie`)
- Logout/Login with your user to apply group changes
> __Tip:__ You can verify if your Tor setup is running correctly using `echo 'PROTOCOLINFO' | nc 127.0.0.1 9051`
> __Tip:__ It's also possible to use Tor without modifying torrc (or to use older versions of Tor clients), by running `zeronet.py --tor disable --proxy 127.0.0.1:9050 --disable_udp`, but then you will lose ability to talk with other .onion addresses.
---
#### Is it possible to use a configuration file?
Any command line configuration flag can also be used as a configuration option. Place these options line-by-line into a file called `zeronet.conf` in your top-level zeronet directory (the one with zeronet.py). Example:
```
[global]
data_dir = my-data-dir
log_dir = my-log-dir
ui_restrict =
1.2.3.4
2.3.4.5
```
To list possible options, use the `zeronet.py --help` command
---
#### How to make Tor work if my ISP or goverment blocks it?
ZeroNet does not include [Tor pluggable transports](https://www.torproject.org/docs/pluggable-transports.html.en) yet. The easiest way to make Tor work in a censored network is to start the Tor browser, configure it to connect to the Tor network with working pluggable transports, and modify ZeroNet's config to use Tor browser's proxy and control port by starting ZeroNet with `--tor_controller 127.0.0.1:9151 --tor_proxy 127.0.0.1:9150` or by adding these parameters to `zeronet.conf`.
```
[global]
tor_controller = 127.0.0.1:9151
tor_proxy = 127.0.0.1:9150
```
---
#### Can I use the same username on multiple machines?
Yes, simply copy the `data/users.json` file to your new machine.
---
#### How to create a "fancy" (non .bit) site address?
Use [vanitygen](https://bitcointalk.org/index.php?topic=25804.0) to generate one. Once you get your keys, create `data/1YourPublicKey...tCkBzAXTKvJk4uj8` directory. Put some files there.
Then navigate to [http://127.0.0.1:43110/1YourPublicKey...tCkBzAXTKvJk4uj8/](http://127.0.0.1:43110/1YourPublicKey...tCkBzAXTKvJk4uj8/). Drag the `0` button to the left and use the sidebar to sign your site.
---
#### How can I register a .bit domain?
You can register .bit domains using [Namecoin](https://namecoin.info/).
Manage your domains using the client's GUI or by the [command line interface](https://github.com/namecoin/wiki/blob/master/How-to-register-and-configure-.bit-domains.md).
After the registration is done you have to edit your domain's record by adding a zeronet section to it, e.g.:
```
{
...
"zeronet": {
"": "1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr",
"blog": "1BLogC9LN4oPDcruNz3qo1ysa133E9AGg8",
"talk": "1TaLk3zM7ZRskJvrh3ZNCDVGXvkJusPKQ"
},
...
}
```
An empty string (`""`) means the top domain, anything other than that is a sub-domain.
> __Tip:__ You can buy Namecoin for Bitcoin or other cryptocurrencies using [shapeshift.io](https://shapeshift.io/).
> __Tip:__ Other possibilities to register .bit domains: [domaincoin.net](https://domaincoin.net/), [peername.com](https://peername.com/), [dotbit.me](https://dotbit.me/)
> __Tip:__ You can verify your domain on [namecha.in](http://namecha.in/), for example: [zeroid.bit](http://namecha.in/name/d/zeroid)
> __Tip:__ You should use only [lower-cased letters, numbers and - in your domains](http://wiki.namecoin.info/?title=Domain_Name_Specification_2.0#Valid_Domains).
> __Tip:__ To make ZeroHello display your domain name instead of your site's Bitcoin address, add a domain key to your content.json. ([Example](https://github.com/HelloZeroNet/ZeroBlog/blob/master/content.json#L6))
---
#### Can I use the generated site address/private key to accept Bitcoin payments?
Yes, it's a standard Bitcoin address. The private key is WIF formatted, so you can import it in most clients.
> __Tip:__ It's not recommended to keep a high amount of money on your site's address, because you have to enter your private key every time you modify your site.
---
#### What happens when someone hosts malicious content?
The ZeroNet sites are sandboxed, they have the same privileges as any other website you visit over the Internet.
You are in full control of what you are hosting. If you find suspicious content you can stop hosting the site at any time.
---
#### Is it possible to install ZeroNet to a remote machine?
Yes, you have to enable the UiPassword plugin by renaming the __plugins/disabled-UiPassword__ directory to __plugins/UiPassword__,
then start ZeroNet on the remote machine using <br>`zeronet.py --ui_ip "*" --ui_password anypassword`.
This will bind the ZeroNet UI webserver to all interfaces, but to keep it secure you can only access it by entering the given password.
> __Tip:__ You can also restrict the interface based on ip address by using `--ui_restrict ip1 ip2`.
> __Tip:__ You can specify the password in the config file by creating a `zeronet.conf` file and adding `[global]` and `ui_password = anypassword` lines to it.
---
#### Is there any way to track the bandwidth ZeroNet is using?
The sent/received bytes are displayed at ZeroNet's sidebar.<br>(open it by dragging the topright `0` button to left)
> __Tip:__ Per connection statistics page: [http://127.0.0.1:43110/Stats](http://127.0.0.1:43110/Stats)
---
#### What happens if two people use the same keys to modify a site?
Every content.json file is timestamped, the clients always accept the newest one with a valid signature.
---
#### Does ZeroNet use Bitcoin's blockchain?
No, ZeroNet only uses the cryptography of Bitcoin for site addresses and content signing/verification.
User identification is based on Bitcoin's [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) format.
Namecoin's blockchain is being used for domain registrations, however clients do not download the blockchain. Blockchain metadata is instead passed over the ZeroNet network.
---
#### Does ZeroNet only support HTML, CSS websites?
ZeroNet is built for dynamic, real-time updated websites, but you can serve any kind of files using it, such as (VCS repositories, your own thin-client, database, etc.
---
#### How can I create a new ZeroNet site?
[Follow these instructions.](../using_zeronet/create_new_site/)
---
#### What happens when I access a site?
- When you want to open a new site it asks for visitor's IP addresses from BitTorrent trackers.
- Initially, a file named __content.json__ is downloaded, which holds all other filenames,
__hashes__ and the site owner's cryptographic signature.
- The downloaded content.json file is __verified__ using the site's __address__ and the site owner's __signature__ from the file.
- Other files (html, css, js...) are then __downloaded__ and verified using their size and SHA512 hash from content.json.
- Each visited site then becomes __also served by you__.
- If the site owner (who has the private key for the site address) __modifies__ the site, then he/she signs
the new content.json and __publishes it to peers__. After the peers have verified the file's
integrity (using the signature), they __download the modified files__ and serve the new content to other peers.
More info:
[ZeroNet sample sites](../using_zeronet/sample_sites/),
[Slideshow about how ZeroNet works](https://docs.google.com/presentation/d/1_2qK1IuOKJ51pgBvllZ9Yu7Au2l551t3XBgyTSvilew/pub)

View File

@ -0,0 +1,20 @@
# Coding standards if you want to collaborate to ZeroNet
- Follow [PEP8](https://www.python.org/dev/peps/pep-0008/)
- Simple is better than complex
- Premature optimization is the root of all evil
### Naming
- ClassNames: Capitalized, CamelCased
- functionNames: starts with lowercase, camelCased
- variable_names: lowercased, under_scored
### Variables
- file_path: File path realtive to working dir (data/17ib6teRqdVgjB698T4cD1zDXKgPqpkrMg/css/all.css)
- inner_path: File relative to site dir (css/all.css)
- file_name: all.css
- file: Python file object
- privatekey: Private key for the site (without _)
### Source files directories and naming
- One class per file is preferred
- Source file name and directory comes from ClassName: WorkerManager class = Worker/WorkerManager.py

View File

@ -0,0 +1,64 @@
# Contributing to ZeroNet
Thank you for using ZeroNet. ZeroNet is a collaborative effort of 67+ decentralization enthusiasts just like you. We appreciate all users that catch bugs, improve documentation and have good ideas of designing new protocols. Here are a few guidelines we ask you to follow to get started with making your contribution.
### You dont have to contribute source code
In fact, a majority of contributors do not submit source code. Even if you like to write programs, other types of contribution are also welcomed.
### Do you like to write?
- Write about ZeroNet.
- Write tutorials to help people set things up.
- Help translate ZeroNet.
- Improve this documentation. This documentation is a written by many community members all over the world.
### Do you like helping people?
- Subscribe to our [issue tracker on GitHub](https://github.com/HelloZeroNet/ZeroNet/issues) and help people solve problems.
- Join us on [Gitter](https://gitter.im/HelloZeroNet/ZeroNet) and IRC channel [#zeronet @ freenode](https://kiwiirc.com/client/irc.freenode.net/zeronet) and help answer questions.
- Set up a seed box and help make the network faster.
### Do you like to make websites?
- Create new ZeroNet sites. Go ahead and make your own blog on ZeroNet. [It is easy and costs little.](../using_zeronet/create_new_site.md)
- “Content is king!” as NoFish puts. The network is worth nothing without content, so we need You to make it succeed.
### Do you like to do research?
- Help us investigate our [hard issues](https://github.com/HelloZeroNet/ZeroNet/labels/help%20wanted).
- Join our discussion of designing new features and protocols, such as [I2P support](https://github.com/HelloZeroNet/ZeroNet/issues/45) and [DHT support](https://github.com/HelloZeroNet/ZeroNet/issues/57).
- Do you own a [Raspberry Pi](https://github.com/HelloZeroNet/ZeroNet#linux-terminal), a [C.H.I.P.](http://127.0.0.1:43110/Blog.ZeroNetwork.bit/?Post:94:Running+ZeroNet+on+a+$9%C2%A0computer) or an [open router](https://github.com/HelloZeroNet/ZeroNet/issues/783)? Try running ZeroNet on it and tell us how well ZeroNet works on your device.
### Do you like to write code?
- If you know Python, you can pick a task from our [issue tracker on GitHub](https://github.com/HelloZeroNet/ZeroNet/issues).
- You are also welcomed develop your own ideas. Before you start, please [open a new discussion](https://github.com/HelloZeroNet/ZeroNet/issues/new) to let the community know, so you can make sure we can share our ideas to make the best out of it.
- Keep your coding style consistent. We ask you to follow our coding convention below.
### Do you like to offer financial support?
- You can [donate bitcoins](donate.md) to support ZeroNet.
## Coding convention
- Follow [PEP8](https://www.python.org/dev/peps/pep-0008/)
- Simple is better than complex
- Premature optimization is the root of all evil
### Naming
- ClassNames: Capitalized, CamelCased
- functionNames: starts with lowercase, camelCased
- variable_names: lowercased, under_scored
### Variables
- file_path: File path relative to working dir (data/17ib6teRqdVgjB698T4cD1zDXKgPqpkrMg/css/all.css)
- inner_path: File relative to site dir (css/all.css)
- file_name: all.css
- file: Python file object
- privatekey: Private key for the site (without `_`)
### Source files directories and naming
- One class per file is preferred
- Source file name and directory comes from ClassName: WorkerManager class = Worker/WorkerManager.py

View File

@ -0,0 +1,127 @@
<link rel=stylesheet href="../../bitcoinbar/bitcoinbar.css">
# Help to keep ZeroNet development alive
## ZeroNet: 2018 first half
<a href="bitcoin:1QDhxQ6PraUZa21ET5fYUCPgdrwBomnFgX?Label=ZeroNet+donation" class="bitcoinbar" data-address="1QDhxQ6PraUZa21ET5fYUCPgdrwBomnFgX" data-goal="9.5"></a>
* General donation towards ZeroNet development
<div>or using PayPal:
<a href="https://www.paypal.me/zeronet/0usd"><img alt="" border="0" src="https://www.paypalobjects.com/webstatic/en_US/btn/btn_donate_pp_142x27.png"></a>
</form>
</div>
---
## Bitmessage support
<a href="bitcoin:1JxwXnjkv5M822aoJEVJawnS2uKnnT216Z?Label=ZeroNet+Bitmessage+donation" class="bitcoinbar" data-address="1JxwXnjkv5M822aoJEVJawnS2uKnnT216Z" data-goal="1.0"></a>
* Send and receive Bitmessage messages using local client's XMLRPC API interface
Benefits:
* Send your permission request to site owner via bitmessage
* Possible private messaging/commenting webui integration to sites
[Github issue](https://github.com/HelloZeroNet/ZeroNet/issues/65)
---
## <s>Namecoin domain support</s> (done in version 0.2.8)
* Use Namecoin domain names to access sites
Benefits:
* Easier to remember site addresses
[Github issue](https://github.com/HelloZeroNet/ZeroNet/issues/31)
---
## DHT support
<a href="bitcoin:122tqTo5jTsZfF4xFodhM54b5HUkeVQL4E?Label=ZeroNet+DHT+donation" class="bitcoinbar" data-address="122tqTo5jTsZfF4xFodhM54b5HUkeVQL4E" data-goal="3.0"></a>
* Peer discovery using DHT
Benefits:
* Peer discovery no longer relies on torrent network
* Ipv6 and Tor peer discovery
[Github issue](https://github.com/HelloZeroNet/ZeroNet/issues/57)
---
## Private sites
<a href="bitcoin:1Q3jV3bAZxKBdMtVjnzfpcsmtXDspjGMnG?Label=ZeroNet+Private+sites" class="bitcoinbar" data-address="1Q3jV3bAZxKBdMtVjnzfpcsmtXDspjGMnG" data-goal="2.0"></a>
* Passworded or public key based peer auth to sites
Benefits:
* Secure control over peers who has access to your site
[Github issue](https://github.com/HelloZeroNet/ZeroNet/issues/62)
---
## <s>Full Tor support</s> (done in version 0.3.5)
* Allow to seed sites and connect other peers using Tor network (Probably depends on DHT support)
Benefits:
* Hiding your IP when distributing new content or downloading site
[Github issue](https://github.com/HelloZeroNet/ZeroNet/issues/60)
---
## <s>Multiuser proxy support</s> (done in version 0.2.7)
* User login/logout using bip32 master seed
Benefits:
* Makes open ZeroNet proxies usable
* Use local ZeroNet more than one user
[Github issue](https://github.com/HelloZeroNet/ZeroNet/issues/58)
---
## Where does the donation go?
The task's received donation goes directly to the developer(s) who successfully and properly integrates the feature (please add your plans and ideas to the issue before you start working on anything big).
# Sponsors
* Better OSX/Safari compatibility made possible by [BrowserStack.com](https://www.browserstack.com/)
<script src='../../jquery.min.js'></script>
<script src='../../bitcoinbar/bitcoinbar.js'></script>

View File

@ -0,0 +1,471 @@
# ZeroNet network protocol
- Every message is encoded using [MessagePack](http://msgpack.org/)
- Every request has 3 parameter:
* `cmd`: The request command
* `req_id`: The request's unique id (simple, incremented nonce per-connection), the client has to include this when reply to the command.
* `params`: Parameters for the request
- Example request: `{"cmd": "getFile", "req_id": 1, "params:" {"site": "1EU...", "inner_path": "content.json", "location": 0}}`
- Example response: `{"cmd": "response", "to": 1, "body": "content.json content", "location": 1132, "size": 1132}`
- Example error response: `{"cmd": "response", "to": 1, "error": "Unknown site"}`
# Handshake
Every connection begins with a handshake by sending a request to the target network address:
Parameter | Description
--- | ---
**crypt** | Null/None, only used in respones
**crypt_supported** | An array of connection encryption methods supported by the client
**fileserver_port** | The client's fileserver port
**onion** | (Only used on tor) The client's onion address
**protocol** | The protocol version the client uses (v1 or v2)
**port_opened** | The client's client port open status
**peer_id** | (Not used on tor) The client's peer_id
**rev** | The client's revision number
**version** | The client's version
**target_ip** | The server's network address
The target initialize the encryption on the socket based on `crypt_supported`, then return:
Return key | Description
--- | ---
**crypt** | The encryption to use
**crypt_supported** | An array of connection encryption methods supported by the server
**fileserver_port** | The server's fileserver port
**onion** | (Only used on tor) The server's onion address
**protocol** | The protocol version the server uses (v1 or v2)
**port_opened** | The server's client port open status
**peer_id** | (Not used on tor) The server's peer_id
**rev** | The server's revision number
**version** | The server's version
**target_ip** | The client's network address
> **Note:** No encryption used on .onion connections, as the Tor network provides the transport security by default.
> **Note:** You can also implicitly initialize SSL before the handshake if you can assume it supported by remote client.
**Example**:
Sent handshake:
```json
{
"cmd": "handshake",
"req_id": 0,
"params": {
"crypt": None,
"crypt_supported": ["tls-rsa"],
"fileserver_port": 15441,
"onion": "zp2ynpztyxj2kw7x",
"protocol": "v2",
"port_opened": True,
"peer_id": "-ZN0056-DMK3XX30mOrw",
"rev": 2122,
"target_ip": "192.168.1.13",
"version": "0.5.6"
}
}
```
Return:
```
{
"protocol": "v2",
"onion": "boot3rdez4rzn36x",
"to": 0,
"crypt": None,
"cmd": "response",
"rev": 2092,
"crypt_supported": [],
"target_ip": "zp2ynpztyxj2kw7x.onion",
"version": "0.5.5",
"fileserver_port": 15441,
"port_opened": False,
"peer_id": ""
}
```
# Peer requests
#### getFile _site_, _inner_path_, _location_, _[file_size]_
Request a file from the client
Parameter | Description
--- | ---
**site** | Site address (example: 1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr)
**inner_path** | File path relative to site directory
**location** | Request file from this byte (max 512 bytes got sent in a request, so you need multiple requests for larger files)
**file_size** | Total size of the requested file (optional)
**Return**:
Return key | Description
--- | ---
**body** | The requested file content
**location** | The location of the last byte sent
**size** | Total size of the file
---
#### streamFile _site_, _inner_path_, _location_, _[file_size]_
Stream a file from the client
**Return**:
Return key | Description
--- | ---
**stream_bytes** | The length of file data after the MessagePack payload
To avoid having python-msgpack serialize large binary strings, the file body is appended directly after the MessagePack payload. For example,
```
> {"cmd": "streamFile", "id": 1, "inner_path": "content.json", "size": 1234}
< {"cmd": "response", "to": 1, "stream_bytes": 1234}
< content of the file
```
> ZeroNet implementation detail: For file segments larger than 256 kb, streaming is enabled by default.
---
#### ping
Checks if the client is still alive
**Return**:
Return key | Description
--- | ---
**body** | Pong
---
#### pex _site_, _peers_, _need_
Exchange peers with the client.
Peers packed to 6 bytes (4byte IP using inet_ntoa + 2byte for port)
Parameter | Description
--- | ---
**site** | Site address (example: 1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr)
**peers** | List of peers that the requester has (packed)
**peers_onion** | List of Tor Onion peers that the requester has (packed)
**need** | Number of peers the requester want
**Return**:
Return key | Description
--- | ---
**peers** | List of IPv4 peers he has for the site (packed)
**peers_onion** | List of Tor Onion peers for this site (packed)
Each element in the `peers` list is a packed IPv4 address.
IP address | Port
---------- | ----
`4 bytes` | `2 bytes`
Each element in the `peers_onion` list is a packed Tor Onion Service address.
B32-decoded onion address | Port
------------------------- | ----
`binary_str[0:-2]` | `binary_str[-2:]`
To restore the onion address, pass the first part through `base64.b32encode` and append `.onion` to the return value.
---
#### update _site_, _inner_path_, _body_, _[diffs]_
Update a site file.
Parameter | Description
--- | ---
**site** | Site address (example: 1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr)
**inner_path** | File path relative to site directory
**body** | Full content of the updated content.json
**diffs** (optional) | [Diff opcodes](#possible-diff-opcodes) for the modified files in the content.json
**Return**:
Return key | Description
--- | ---
**ok** | Thanks message on successful update :)
##### Diffs format
A dict that contains the modifications
- Key: changed file's relative path to content.json (eg.: `data.json`)
- Value: The list of diff opcodes for the file (eg.: `[['=', 5], ['+', '\nhello new line'], ['-', 6]]`)
##### Possible diff opcodes:
Opcode | Description
--- | ---
**['=', number of same characters]** | Have not changed part of the file (eg.: `['=', 5]`)
**['+', new text]** | Added characters (eg.: `['+', '\nhello new line']`)
**['-', number of removed characters]** | Full content of the updated file (eg.: `['-', 6]`)
After the update received, the client tries to patch the files using the diffs.
If it failes to match the sha hash provided by the content.json (had different version of the file) it automatically re-downloads the whole file from the sender of the update.
> __Note:__ The patches are limited to 30KB per file and only used for .json files
---
#### listModified _site_, _since_
Lists the content.json files modified since the given parameter. It used to fetch the site's user submitted content.
Parameter | Description
--- | ---
**site** | Site address (example: 1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr)
**since** | List content.json files since this timestamp.
**Return**:
Return key | Description
--- | ---
**modified_files** | Key: content.json inner_path<br>Value: last modification date
**Example**:
```json
> zeronet.py --silent peerCmd 127.0.0.1 15441 listModified "{'site': '1BLogC9LN4oPDcruNz3qo1ysa133E9AGg8', 'since': 1497507030}"
{
"to": 1,
"cmd": "response",
"modified_files": {
"data/users/1NM9k7VJfrb1UWw5agAvyRfSn3ws1wTJ5U/content.json": 1497579272,
"data/users/1QEfmMwKVxgR4rkREbdJYjgUmF3Zy8pwHt/content.json": 1497565986,
"data/users/16NS3rBdW9zpLmLSQoD8nLTtNVsRFtVBhd/content.json": 1497575039,
"data/users/1CjXarXgvcNeCJ2nMQxUi4DRFWp3GEur2W/content.json": 1497513808,
"data/users/1L5rGDgTs4W2V7gekSvJNhKa7XaHkVwotD/content.json": 1497615798,
"data/users/1LWuc6JBhUGrKEAh1aPrPU85dEMcKmg3pS/content.json": 1497594716,
"data/users/1KdnTJVBGzEZrJppFZtzfG9chukuMv8xSb/content.json": 1497584640,
"data/users/1GMNmr2bDPbT4c8yVnyCoDHke52CNCdqAa/content.json": 1497614188,
"data/users/1GRm9rED83Tkfi3iWS9m3LWHiRpPZehWLd/content.json": 1497827772,
"data/users/12Ugp53jiMdvj1Kxa1w7c2LcXUBdGPs1oK/content.json": 1497692901,
"data/users/1F6BMqittjWUStzUbRXm2kG2GQ3RdBLqFQ/content.json": 1497571485,
"data/users/1GgNo3CmxPd7n2pMSF3uyqf1XHvgtTUqCe/content.json": 1497560829,
"data/users/16nArdxrSaNThNp83kL8E6NLL9WD98iUne/content.json": 1497627929,
"data/users/16CAJkbfNRxNJq4aKdrZ2MSYFfFGvQ8JPi/content.json": 1497664899,
"data/users/1DrBS2sTD3BX5BBxG8eqYsxXSvGt9kc5HE/content.json": 1497632000,
"data/users/19sggoAZ4hcorrrfWoFWP9rwfpVsL29cnZ/content.json": 1497928134,
"data/users/1NYpJupegoTXL4cFpkNdLNJ4XaAhTNhPe1/content.json": 1497535771,
"data/users/1R67TfYzNkCnh89EFfGmXn5LMb4hXaMRQ/content.json": 1497691787,
"data/users/1C9HXUYFSVafLxanwkaFPZRcRgCEGsj2Cn/content.json": 1497572833,
"data/users/1LgoHzNGWeijeZbJ8a1YgGjMCnjaM4BWG/content.json": 1497620232,
"content.json": 1497623639
}
}
```
---
#### getHashfield _site_
Get the client's downloaded [optional file ids](#optional-file-id).
Parameter | Description
--- | ---
**site** | Site address (example: 1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr)
**Return**:
Return key | Description
--- | ---
**hashfield_raw** | Optional file ids encoded using `array.array("H", [1000, 1001..]).tostring()`
**Example**:
```json
> zeronet.py --silent peerCmd 192.168.1.13 15441 getHashfield "{'site': '1Gif7PqWTzVWDQ42Mo7np3zXmGAo3DXc7h'}
{
'to': 1,
'hashfield_raw': 'iG\xde\x02\xc6o\r;...',
'cmd': 'response'
}
```
---
#### setHashfield _site_, _hashfield_raw_
Set the list of [optional file ids](#optional-file-id) that the requester client has.
Parameter | Description
--- | ---
**site** | Site address (example: 1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr)
**hashfield_raw** | Optional file ids encoded using `array.array("H", [1000, 1001..]).tostring()`
**Return**:
Return key | Description
--- | ---
**ok** | Updated
---
#### findHashIds _site_, _hash_ids_
Queries if the client know any peer that has the requested hash_ids
Parameter | Description
--- | ---
**site** | Site address (example: 1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr)
**hash_ids** | List of optional file ids the client currently looking for
**Return**:
Return key | Description
--- | ---
**peers** | Key: Optional file id<br>Value: List of ipv4 peers encoded using `socket.inet_aton(ip) + struct.pack("H", port)`
**peers_onion** | Key: Optional file id<br>Value: List of onion peers encoded using `base64.b32decode(onion.replace(".onion", "").upper()) + struct.pack("H", port)`
**Example**:
```json
> zeronet.py --silent peerCmd 192.168.1.13 15441 findHashIds "{'site': '1Gif7PqWTzVWDQ42Mo7np3zXmGAo3DXc7h', 'hash_ids': [59948, 29811]}"
{
'to': 1,
'peers': {
29811: [
'S&9\xd3Q<',
'>f\x94\x98N\xa4',
'gIB\x90Q<',
'\xb4\xady\xf7Q<'
],
59948: [
'x\xcc>\xf6Q<',
'S\xa1\xddkQ<',
'\x05\xac\xe8\x8dQ<',
'\x05\xc4\xe1\x93Q<',
'Q\x02\xed\nQ<'
]
},
'cmd': 'response',
'peers_onion': {
29811: ['\xc7;A\xce\xbc\xd9O\xe2w<Q<'],
59948: ['\xc7;A\xce\xbc\xd9O\xe2w<Q<']
}
}
```
##### Optional file id
Integer representation of the first 4 character of the hash:
```
>>> int("ea2c2acb30bd5e1249021976536574dd3f0fd83340e023bb4e78d0d818adf30a"[0:4], 16)
59948
```
---
#### checkport _port_
Check requested port of the other peer.
Parameter | Description
--- | ---
**port** | Port which will be checked.
**Return**:
Return key | Description
--- | ---
**status** | Status of the port ("open" or "closed")
**ip_external** | External IP of the requestor
---
# Bigfile Plugin
#### getPieceFields _site_
Returns all big file [piecefield](#bigfile-piecefield) that client has for that site in a dict.
Parameter | Description
--- | ---
**site** | Requested site
**Return**:
Return key | Description
--- | ---
**piecefields_packed** | Key: Bigfile's sha512/256 [merkle root hash](#bigfile-merkle-root)<br>Value: Packed [piecefield](#bigfile-piecefield)
---
#### setPieceFields _site_, _piecefields_packed_
Set the client's [piecefields](#picefield) for that site.
Parameter | Description
--- | ---
**site** | Requested site
**piecefields_packed** | Key: Bigfile's sha512/256 [merkle root hash](#bigfile-merkle-root)<br>Value: Packed [piecefield](#bigfile-piecefield)
**Return**:
Return key | Description
--- | ---
**ok** | Updated
##### Bigfile piecefield
Holds the the big files downloaded pieces information in a simple string with 1/0 values. (1 = Downloaded, 0 = Not downloaded)
> __Example__: `1110000001` means the file is sized 9-10MB and the client downloaded the first 3MB and the last 1MB at 1MB piecesize.
**Packed format**:
Turns the string to an list of int by counting the repeating characters starting with `1`.
> __Example__: `1110000001` to `[3, 6, 1]`, `0000000001` to `[0, 9, 1]`, `1111111111` to `[10]`
After the conversion it turns it to more efficient [typed array](https://docs.python.org/2/library/array.html) using `array.array('H', piecefield)`
##### Bigfile merkle root
During the big file hashing procedure, in addition to storing the per-piece sha512/256 hash digests in the [piecemap](#bigfile-piecemap) file, the algorithm also calculates the SHA-512/256 merkle root of the file using the [merkle-tools](https://github.com/tierion/merkle-tools) implementation.
The merkle root is only used as an ID to identify the big file, not (yet) for verifying the pieces.
> __Note__: The merkle root is chosen to identify the file, instead of the file's actual SHA-512/256 hash. Obviously, using the latter results in hashing the same file twice. (once for piecemap once for the whole file)
> __Note__: The merkle root is not used to verify the integrity of the pieces or the big file, because doing so would take more bandwidth and space to transfer and store the merkle-proofs for partial verification, than the per-piece hash map file itself.
##### Bigfile piecemap
It holds the per-piece SHA-512/256 hashes. The piece size and the picemap filename is defined in `content.json`, eg.:
```
...
"files_optional": {
"bigfile.mp4": {
"piece_size": 1048576,
"piecemap": "bigfile.mp4.piecemap.msgpack",
"sha512": "d1f0d150e1e73bb1e684d370224315d7ba21e656189eb646ef7cc394d033bc2b",
"size": 42958831
},
...
```
Having the following data structure, the piecemap file is packed into the [msgpack](https://msgpack.org/) format:
```
{
b'bigfile.mp4': {b'sha512_pieces': [
b"e\xde\x0fx\xec\xc5LZ9\x0e\xe7\x85E\x1b\xd5\xe4C'\xe7req\xe3<\xff\\\xbb\xc8b\xc2\xc1\x8e",
b'\xef\xe8\xed\xfe\x16/\x96\xdb;;\x06n[8_\x06\x9ak|\xe1\x9f\xe1\xaf\x87\x96\xdd\xfd\x9bEf\xd9!',
b'\x1c\xd6-\x1f\xce\xde{\xcd\x01\x93un =D\x0brmB-\xd1\x8c\xbf\xfe\xca\x8a\x1c\xf60\xbb\xedD',
b'\x1aQdF\xd2\xbc\xdff{\xb7\x89\xf2\xd3\r\xa9\xe1\xefA-V\x18\xa4\xc8e\x13\x88v\x13\\&\xfbW',
...
]}
}
```

90
docs/zh/index.md Normal file
View File

@ -0,0 +1,90 @@
## 什么是ZeroNet
ZeroNet是使用比特币加密技术和BitTorrent构建的**抗审查分布式网络**.
用户可以在ZeroNet发布静态或动态的网站访客也可以选择去成为网站的服务器。只要有一个节点在网站就会保持在线。
站长更新网站后,所有服务于这个网站(作为服务器)的节点(以前的访客)只会接收网站更新后增加的内容。
ZeroNet内置SQL数据库便于开发规模大的网站。数据库会以增量更新的方式同步到有这个网站的节点。
## 为什么要开发零网ZeroNet
* 我们信仰开放、自由、无审查的通讯。
* 无审查:一旦内容发布,便不可删除。
* 没有单点故障:即便只有一个节点,内容仍会保持在线。
* 不可能被关闭:零网在何处无人知道,因为它无处不在。网站的内容都是由愿意为数据作服务器的用户来提供的。
* 高速零网使用BitTorrent技术传输数据比中心化服务器还要快。
* 离线可用:网络不可用时也可以访问网站。
* 安全: 网站内容的所有权由Bitcoin钱包的同种加密技术所保护。
[comment]: <> (I'm unsure about the following bit. Thoughts?)
[comment]: <> (# What problem is ZeroNet solving?)
[comment]: <> (When Tim Berners-Lee created the internet, he meant for it to be free. Not surveilled nor censored. And [he is still fighting for that](http://edition.cnn.com/2014/03/12/tech/web/tim-berners-lee-web-freedom/).)
[comment]: <> (The internet is centralized mainly in two places: Content and Domain Names (URLs) are hosted and controlled by central servers. If you control the central servers (and if you are powerful enough you do) you control the network.)
[comment]: <> (**Decentralized content storage**)
[comment]: <> (ZeroNet tackles the content storage problem by giving everyone the ability to store content. Site visitors can choose to store a website on their computers, and when they do this they also help to serve the site to other users. The site is online even if only one user is hosting it.)
[comment]: <> (**Shared DNS cache**)
[comment]: <> (Site addresses on ZeroNet are cached by all network members. When you type a ZeroNet site URL on your browser this will query other peers connected to you about the site. If one of these peers happen to have the site they will send it to you, if not, they will forward your query along.)
[comment]: <> (This architecture means that when a site URL is created, as long as one peer is serving it, there is no way to take the URL down.)
## 特性
* 简单,零配置安装。
* 无需密码,基于[BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)的授权: 账号的所有权由Bitcoin钱包的同种加密技术所保护。
* 站点实时更新,不需要刷新。
* Namecoin .bit 域名支持。
* SQL 数据库支持: 简化了站点开发,减少了页面加载时间。
* 匿名性: 完整的Tor网络支持使用.onion而非ipv4地址。
* TLS加密连接。
* 自动使用uPnP打开端口。
* 多用户插件openproxy
* 可以在任何操作系统和浏览器上使用。
## 零网是如何工作的?
* 安装并启动零网后,访问类似于如下所示的地址打开网站。
`http://127.0.0.1:43110/{零网站点地址}`
(例如 `http://127.0.0.1:43110/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D`).
* 零网用BitTorrent网络寻找为这个网站做种的节点并向节点索要网站数据(HTML, CSS, JS...)。
* 客户端会为每个访问过的网站服务,站点也可以手动添加黑名单或移除。
* 每个网站都有一个网站文件列表包含站长用私钥生成的SHA512哈希和一个签名。
* 站长修改网站后,签名新文件列表,并发布到其他节点。
节点验证完列表完整性后(用签名),下载已修改的文件再传送给其他节点。
##### [关于零网加密技术、内容更新和多用户站点的幻灯片 &raquo;](https://docs.google.com/presentation/d/1_2qK1IuOKJ51pgBvllZ9Yu7Au2l551t3XBgyTSvilew/pub?start=false&loop=false&delayms=3000)
## 截图
![截图](./img/zerohello.png)
![ZeroTalk](./img/zerotalk.png)
##### [更多截图 &raquo;](/using_zeronet/sample_sites/)
## 当前局限
* <strike>没有类似于torrent的文件分割、大文件的支持</strike> (BigFile插件已实现)
* 文件传输未压缩 <strike>或加密</strike> (TLS 加密已添加)
* 无法创建私有站点。
## 帮助这个项目存活
Bitcoin: 1QDhxQ6PraUZa21ET5fYUCPgdrwBomnFgX
[Full donation page](help_zeronet/donate/)
### 谢谢!
* 更多信息、帮助、零网站点: [http://www.reddit.com/r/zeronet/](http://www.reddit.com/r/zeronet/)
* 交谈: [#zeronet @ FreeNode](https://kiwiirc.com/client/irc.freenode.net/zeronet) 或在 [gitter](https://gitter.im/HelloZeroNet/ZeroNet)

View File

@ -0,0 +1,148 @@
# Certificate Authority
An account without password? A certificate for me? You realize the ID system of ZeroNet does not conform to convention. In this section, you are going to learn about how user certificate and certificate authority work in ZeroNet.
## What does a certificate authority do?
In ZeroNet, everything is signed by Bitcoin signing keys. A certificate provides a unique and memorizable name for a Bitcoin address. A certificate authority (or an ID provider) is responsible for proving the relationship between a unique friendly name and a Bitcoin address.
## Certificate format
### Body
The body of a certificate contains a Bitcoin address, a portal type, and a memorizable user name.
```
[BitcoinAddress]#[PortalType]/[UserName]
```
**Example:**
```
1H28iygiKXe3GUMcD77HiifVqtf3858Aft#web/hellozeronet
```
- Bitcoin address: `1H28iygiKXe3GUMcD77HiifVqtf3858Aft`
- Portal type: `web`
- User name: `hellozeronet`
**General rules:**
The Bitcoin address, the portal type and the user name **must not** contain the character `#`, `@` or `/`
Only 0-9 and a-z are allowed in a user name. All English letters in a user name **must** be in lower case. Characters not in the allowed set **must not** be used as parts of a user name. A user name **should not** be too long. A user name **should** be legible and **should not** interfere with user interface rendering.
A user name **must** be unique in the pool of all registered user names.
### Signature
A certificate signing algorithm loads a secret signing key and generates a deterministic Bitcoin signature for the body.
**From the source code:**
```python
sign = os.popen("python zeronet.py --debug cryptSign %s#bitmsg/%s %s 2>&1" % (auth_address, user_name, config.site_privatekey)).readlines()[-1].strip()
```
### Certificate
By looking at the source code of ZeroID, we know how a certificate is stored in its public database.
```python
data["users"][user_name] = "bitmsg,%s,%s" % (auth_address, sign)
```
**Example:**
```
"hellozeronet": "web,1H28iygiKXe3GUMcD77HiifVqtf3858Aft,HA2A+iKekECD3hasrsN8IrR86BnXQ63kPH+9A85JLO9hLUpRJTBn62UfnuuF92B9CIc6+EewAIqzIn9UoVq2LPA="
```
A certificate can be stored in various formats. However, all formats must include:
- The Bitcoin address: `1H28iygiKXe3GUMcD77HiifVqtf3858Aft`
- The portal type: `web`
- The user name: `hellozeronet`
- The signature from authority: `HA2A+iKekECD3hasrsN8IrR86BnXQ63kPH+9A85JLO9hLUpRJTBn62UfnuuF92B9CIc6+EewAIqzIn9UoVq2LPA=`
## Usage in `content.json`
Site owners can choose which certificate authorities to trust.
The Blue Hub, for example, accepts certificates signed by ZeroID. This rule is defined in its `data/users/content.json`
- The ID provider has a friendly name: `zeroid.bit`
- The public key digest of the ID provider is: `1iD5ZQJMNXu43w1qLB8sfdHVKppVMduGz`
```json
"user_contents": {
"cert_signers": {
"zeroid.bit": [
"1iD5ZQJMNXu43w1qLB8sfdHVKppVMduGz"
]
}
}
```
Every user presents his certificate in the manifest file in his Bitcoin folder. For example, `data/users/1J3rJ8ecnwH2EPYa6MrgZttBNc61ACFiCj/content.json` says:
```json
{
"address": "1BLueGvui1GdbtsjcKqCf4F67uKfritG49",
"cert_auth_type": "web",
"cert_sign": "HPiZsWEJ5eLnspUj8nQ75WXbSanLz0YhQf5KJDq+4bWe6wNW98Vv9PXNyPDNu2VX4bCEXhRC65pS3CM7cOrjjik=",
"cert_user_id": "nofish@zeroid.bit",
"files": {
"data.json": {
"sha512": "8e597412a2bc2726ac9a1ee85428fb3a94b09f4e7a3f5f589119973231417b15",
"size": 21422
}
},
"inner_path": "data/users/1J3rJ8ecnwH2EPYa6MrgZttBNc61ACFiCj/content.json",
"modified": 1492458379,
"signs": {
"1J3rJ8ecnwH2EPYa6MrgZttBNc61ACFiCj": "G8kaZIGAstsiWLVY20e2ogJQi4OO+QuwqJ9GTj3gz7YleST/jst7RQH7hDn0uf8BJMBjFs35H3LPhNHHj4jueh8="
}
}
```
Site specific:
- Expected site URL: `"address": "1BLueGvui1GdbtsjcKqCf4F67uKfritG49"`
- Expected file path: `"inner_path": "data/users/1J3rJ8ecnwH2EPYa6MrgZttBNc61ACFiCj/content.json"`
Certificate information:
- ID provider: `zeroid.bit`
- User name: `nofish`
- User Bitcoin address: `1J3rJ8ecnwH2EPYa6MrgZttBNc61ACFiCj`
- Portal type: `web`
- Signature from ID provider: `HPiZsWEJ5eLnspUj8nQ75WXbSanLz0YhQf5KJDq+4bWe6wNW98Vv9PXNyPDNu2VX4bCEXhRC65pS3CM7cOrjjik=`
### The verifying process
1. The verifying algorithm reads `data/users/content.json` to determine what is the expected site for the user content.
2. The verifying algorithm reads `data/users/content.json` to look up the public key digest of the ID provider.
3. Given a user Bitcoin address, a portal type and a user name, the verifying algorithm reconstructs the body of the certificate.
4. The verifying algorithm checks the signature from the ID provider, with the public key defined in `data/users/content.json`, to ensure the authenticity of the certificate body.
5. The verifying algorithm loads the user public key and checks the authenticity of the user content.
## Features and limitations of certificate authorities
- A certificate authority provides memorizable names for user public key digests. It also helps mitigate spam and unsolicited content.
- A user does not have to give away secret information such as passwords. In addition, a user only has to authenticate once.
- A certificate authority does not have to be approved by any ZeroNet developers. A site owner can choose which certificate authorities to trust for the sake of user content quality.
- A certificate authority is responsible for maintaining its user name pool.
- ZeroID does not revoke or renew certificates.
## Can I live without certificate authorities?
Generally, a certificate is required when you add things to someone else's site. You do not need a certificate when you are modifying your own site.

View File

@ -0,0 +1,371 @@
# Structure of content.json
Every ZeroNet site has a `content.json` file. ([Example content.json file](https://github.com/HelloZeroNet/ZeroTalk/blob/master/content.json))
This file will carry, among other things, a list of all files on your site and a signature created with your private key. This is used to ensure authenticity of site files and avoid tampering (ie: only you, or people you trust, can update your site's content).
Here is a list of supported `content.json` keys:
---
## Generated automatically
_These keys are added automatically when the site is created or cloned._
### address
Your site address
**Example**: 1TaLk3zM7ZRskJvrh3ZNCDVGXvkJusPKQ
---
### address_index
The site address's BIP32 sub-key index of your BIP32 seed. Auto-added when you clone a site. It allows recovery of the site's privatekey from your BIP32 seed.
**Example**: 30926910
---
### cloned_from
Only for cloned sites. The site address where the site is cloned from.
**Example**: 1BLogC9LN4oPDcruNz3qo1ysa133E9AGg8
---
### clone_root
Only for cloned sites. The sub-directory on the site which this was cloned from.
**Example**: template-new
---
### files
Size and sha512 hashes of automatically downloaded files contained in your site. Automatically added by the command `zeronet.py siteSign siteaddress privatekey`.
**Example**:
```python
"css/all.css": {
"sha512": "869b09328f07bac538c313c4702baa5276544346418378199fa5cef644c139e8",
"size": 148208
}
```
---
### files_optional
Size and sha512 hashes of optional files contained in your site. Automatically added by the command `zeronet.py siteSign siteaddress privatekey`.
**Example**:
```python
"data/myvideo.mp4": {
"sha512": "538c09328aa52765443464135cef644c144346418378199fa5cef61837819538",
"size": 832103
}
```
---
### modified
Time when the content.json was generated.
**Example**: 1425857522.076
---
### sign (deprecated)
ECDSA sign of the content.json file content. (keys sorted, without whitespace and the `sign` and `signers_sign` nodes). For backward compatibility, will be removed soon.
**Example**:
```python
"sign": [
43117356513690007125104018825100786623580298637039067305407092800990252156956,
94139380599940414070721501960181245022427741524702752954181461080408625270000
],
```
---
### signers_sign
Possible signer addresses for the root content.json signed using the site address private key. Multiple entries are allowed here, allowing for site Multisig functionality.
**Format of the signed string**: [number_of_signers_required]:[signer address],[signer address]
*Example*:
```
signs_required: 1:1PcxwuHYxuJEmM4ydtB1vbiAY6WkNgsz9G,1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE
signers_sign: MEUCIQDuz+CzOVvFkv1P2ra9i5E1p1G0/1cOGecm7GpLpMLhuwIgBIbCL0YHXD1S2+x48QS5VO/rISrkdLiUR+o+x1X0y1A=
```
The above signed message is signed using the address "1PcxwuHYxuJEmM4ydtB1vbiAY6WkNgsz9G".
---
### signs
ECDSA signature for the the content.json file content:
- `sign`, `signs` JSON nodes removed
- JSON dumped with keys sorted alphabetically, without whitespace
- Signature generated on the dumped data, using Electrum Bitcoin message signature format:
* [Message encoding](https://github.com/vbuterin/pybitcointools/blob/87806f3c984e258a5f30814a089b5c29cbcf0952/bitcoin/main.py#L405): `sha256("\x18" || "Bitcoin Signed Message:\n" || num_to_var_int(len(message)) || message)`
* [Serialization format](https://github.com/MuxZeroNet/zerolib/blob/f13126e04bf99b1b416a7ea5b5cad7924cdc15a4/zerolib/integrity/bitcoin.py#L82-L93): `recovery_id || r || s`, where 27 ≤ recovery_id ≤ 30; signature length = 1 + 32 + 32 = 65 bytes.
* Double vertical bar `||` denotes byte concatenation.
**Example**:
```python
"signs": {
"1TaLk3zM7ZRskJvrh3ZNCDVGXvkJusPKQ": "G6/QXFKvACPQ7LhoZG4fgqmeOSK99vGM2arVWkm9pV/WPCfc2ulv6iuQnuzw4v5z82qWswcRq907VPdBsdb9VRo="
},
```
----
### zeronet_version
The ZeroNet version used to generate content.json file.
**Example**: 0.2.5
---
## Optional Settings
_These options can be added if the functionality is needed._
### background-color
Background color of the wrapper
**Example**: #F5F5F5
---
### cloneable
Allow to clone the site if **true**.
To make your site properly cloneable you have to have a separate folder of data
files for a clean start (e.g. without any blog posts). To do this you have to
add the **-default** postfix to your data files and directories. During the
cloning process, only directories with the **-default** postfix are
copied. The postfix is removed from the new site.
---
### description
Description of your site, displayed under the site title on ZeroHello.
**Example**: Decentralized forum demo
---
### domain
Namecoin domain name of your site. ZeroHello will link to this if the user has Zeroname plugin enabled.
**Example**: Blog.ZeroNetwork.bit
---
### ignore
Do not sign files matching this pattern.
**Example**: `((js|css)/(?!all.(js|css))|data/users/.*)` (ignore all js and css files except all.js and all.css and don't add anything from the `data/users/` directory)
Note: [Some restrictions](#regular-expression-limitations) apply to regular expressions.
---
### includes
Include another content.json in the site. This is typically used for subsequent content.json files that are used to govern user data.
**Example**:
```python
"includes": {
"data/users/content.json": {
"signers": [ # Possible signers address for the file
"1LSxsKfC9S9TVXGGNSM3vPHjyW82jgCX5f"
],
"signers_required": 1 # The *number* of Valid signs required to accept the file (Multisig possibility),
"files_allowed": "data.json", # Preg pattern for the allowed files in the include file
"includes_allowed": false, # Whether nested includes are allowed
"max_size": 10000, # Max allowed size of included content.json and files it signs (in bytes)
}
}
```
---
### merged_type
The type of merger this site is a part of.
**Example**: `ZeroMe`
---
### optional
Preg pattern of optional files.
**Example**: `(data/mp4/.*|updater/.*)` (everything in data/mp4 and updater directory is optional)
Note: [Some restrictions](#regular-expression-limitations) apply to regular expressions.
---
### signs_required
The **number** of valid signs required to accept the file. Allows for Multisig functionality.
**Example**: 1
---
### title
The site's title, visible in the browser title and on ZeroHello.
**Example**: ZeroTalk
----
### translate
Files need be translated. (use language json files in the `languages` directory)
**Example**: ["index.html", "js/all.js"]
----
### favicon
The site's favicon. Replaces the default ZeroNet logo with a site-specific icon. Can be a .ico, .png, .svg, etc.
**Example**: favicon.ico
----
### user_contents
Rules of allowed user content within the current directory.
Node | Description
--- | ---
**archived** | Delete the specified user content directory that is signed earler than the specified timestamp (key: directory name, value: timestamp)
**archived_before** | Delete all user content directory if that is signed earler than the specified timestamp
**cert_signers** | Accepted domains and valid signer addresses
**permission_rules** | Allowed file names and total directory size based on cert domain or authorization method
**permissions** | Per-user permissions. (false = banned user)
**Example**:
```python
"user_contents": {
"archived": {
"1165u6pt5mQNFjyhMVwy6azB7bZuQGLA9b": 1523088096
},
"archived_before": 1523088096,
"cert_signers": {
"zeroid.bit": [ "1iD5ZQJMNXu43w1qLB8sfdHVKppVMduGz" ]
},
"permission_rules": {
".*": {
"files_allowed": "data.json",
"max_size": 10000
},
"bitid/.*@zeroid.bit": { "max_size": 40000 },
"bitmsg/.*@zeroid.bit": { "max_size": 15000 }
},
"permissions": {
"bad@zeroid.bit": false,
"nofish@zeroid.bit": { "max_size": 100000 }
}
}
```
Note: [Some restrictions](#regular-expression-limitations) apply to regular expressions.
----
### viewport
Content for the viewport meta tag. (Used for mobile-friendly pages)
**Example**: width=device-width, initial-scale=1.0
----
## Regular expression limitations
To avoid the [ReDoS](https://en.wikipedia.org/wiki/ReDoS) algorithmic complexity attack, the following restrictions are applied to each pattern:
- `.` character is mandatory before repetition characters of `*,+,{`
- Maximum 9 repetitions are allowed in a single pattern
- The maximum length of a pattern is 255 characters
### Examples:
- `((?!json).)*$` not allowed, because of `)` before the `*` character. Possible fix: `.*(?!json)$`
- `(.*.epub|.*.jpg|.*.jpeg|.*.png|data/.*.gif|.*.avi|.*.ogg|.*.webm|.*.mp4|.*.mp3|.*.mkv|.*.eot)` not allowed, because it has 12 `.*` repetition patterns. Possible fix: `.*(epub|jpg|jpeg|png|data/gif|avi|ogg|webm|mp4|mp3|mkv|eot)`

View File

@ -0,0 +1,211 @@
# Structure of dbschema.json
[Example dbschema.json file](https://github.com/HelloZeroNet/ZeroTalk/blob/master/dbschema.json)
The code below will do the following:
- If an updated data/users/*/data.json file is received (eg.: a user posted something):
- Every row in `data["topics"]` is loaded to the `topic` table
- Every key in `data["comment_votes"]` is loaded to the `comment_vote` table as `comment_hash` col and the values stored in same line as `vote`
- If an updated data/users/content.json file is received (eg.: new user created):
- The `"user_id", "user_name", "max_size", "added"` key in value of `content["include"]` is loaded into the `user` table and the key is stored as `path`
> Note: [Some restriction](content_json/#regular-expressions-limitations) apply to regular expressions to avoid possible ReDoS vulnerability.
```json
{
"db_name": "ZeroTalk", # Database name (only used for debugging)
"db_file": "data/users/zerotalk.db", # Database file relative to site's directory
"version": 2, # 1 = Json table has path column that includes directory and filename
# 2 = Json table has separate directory and file_name column
# 3 = Same as version 2, but also has site column (for merger sites)
"maps": { # Json to database mappings
".*/data.json": { # Regex pattern of file relative to db_file
"to_table": [ # Load values to table
{
"node": "topics", # Reading data.json[topics] key value
"table": "topic" # Feeding data to topic table
},
{
"node": "comment_votes", # Reading data.json[comment_votes] key value
"table": "comment_vote", # Feeding data to comment_vote table
"key_col": "comment_hash",
# data.json[comment_votes] is a simple dict, the keys of the
# dict are loaded to comment_vote table comment_hash column
"val_col": "vote"
# The data.json[comment_votes] dict values loaded to comment_vote table vote column
}
],
"to_keyvalue": ["next_message_id", "next_topic_id"]
# Load data.json[next_topic_id] to keyvalue table
# (key: next_message_id, value: data.json[next_message_id] value)
},
"content.json": {
"to_table": [
{
"node": "includes",
"table": "user",
"key_col": "path",
"import_cols": ["user_id", "user_name", "max_size", "added"],
# Only import these columns to user table
"replaces": {
"path": {"content.json": "data.json"}
# Replace content.json to data.json in the
# value of path column (required for joining)
}
}
],
"to_json_table": [ "cert_auth_type", "cert_user_id" ] # Save cert_auth_type and cert_user_id directly to json table (easier and faster data queries)
}
},
"tables": { # Table definitions
"topic": { # Define topic table
"cols": [ # Cols of the table
["topic_id", "INTEGER"],
["title", "TEXT"],
["body", "TEXT"],
["type", "TEXT"],
["parent_topic_hash", "TEXT"],
["added", "DATETIME"],
["json_id", "INTEGER REFERENCES json (json_id)"]
],
"indexes": ["CREATE UNIQUE INDEX topic_key ON topic(topic_id, json_id)"],
# Indexes automatically created
"schema_changed": 1426195822
# Last time of the schema changed, if the client's version is different then
# automatically destroy the old, create the new table then reload the data into it
},
"comment_vote": {
"cols": [
["comment_hash", "TEXT"],
["vote", "INTEGER"],
["json_id", "INTEGER REFERENCES json (json_id)"]
],
"indexes": ["CREATE UNIQUE INDEX comment_vote_key ON comment_vote(comment_hash, json_id)", "CREATE INDEX comment_vote_hash ON comment_vote(comment_hash)"],
"schema_changed": 1426195826
},
"user": {
"cols": [
["user_id", "INTEGER"],
["user_name", "TEXT"],
["max_size", "INTEGER"],
["path", "TEXT"],
["added", "INTEGER"],
["json_id", "INTEGER REFERENCES json (json_id)"]
],
"indexes": ["CREATE UNIQUE INDEX user_id ON user(user_id)", "CREATE UNIQUE INDEX user_path ON user(path)"],
"schema_changed": 1426195825
},
"json": { # Json table format only required if you have specified to_json_table pattern anywhere
"cols": [
["json_id", "INTEGER PRIMARY KEY AUTOINCREMENT"],
["directory", "TEXT"],
["file_name", "TEXT"],
["cert_auth_type", "TEXT"],
["cert_user_id", "TEXT"]
],
"indexes": ["CREATE UNIQUE INDEX path ON json(directory, site, file_name)"],
"schema_changed": 4
}
}
}
```
## Example for data.json file
```json
{
"next_topic_id": 2,
"topics": [
{
"topic_id": 1,
"title": "Newtopic",
"body": "Topic!",
"added": 1426628540,
"parent_topic_hash": "5@2"
}
],
"next_message_id": 19,
"comments": {
"1@2": [
{
"comment_id": 1,
"body": "New user test!",
"added": 1423442049
}
],
"1@13": [
{
"comment_id": 2,
"body": "hello",
"added": 1424653288
},
{
"comment_id": 13,
"body": "test 123",
"added": 1426463715
}
]
},
"topic_votes": {
"1@2": 1,
"4@2": 1,
"2@2": 1,
"1@5": 1,
"1@6": 1,
"3@2": 1,
"1@13": 1,
"4@5": 1
},
"comment_votes": {
"5@5": 1,
"2@12": 1,
"1@12": 1,
"33@2": 1,
"45@2": 1,
"12@5": 1,
"34@2": 1,
"46@2": 1
}
}
```
## Example for content.json file
```json
{
"files": {},
"ignore": ".*/.*",
"includes": {
"13v1FwKcq7dx2UPruFcRcqd8s7VBjvoWJW/content.json": {
"added": 1426683897,
"files_allowed": "data.json",
"includes_allowed": false,
"max_size": 10000,
"signers": [
"13v1FwKcq7dx2UPruFcRcqd8s7VBjvoWJW"
],
"signers_required": 1,
"user_id": 15,
"user_name": "meginthelloka"
},
"15WGMVViswrF13sAKb7je6oX3UhXavBxxQ/content.json": {
"added": 1426687209,
"files_allowed": "data.json",
"includes_allowed": false,
"max_size": 10000,
"signers": [
"15WGMVViswrF13sAKb7je6oX3UhXavBxxQ"
],
"signers_required": 1,
"user_id": 18,
"user_name": "habla"
}
}
}
```

View File

@ -0,0 +1,62 @@
# Getting Started
ZeroNet allows you to publish static and dynamic websites on a distributed web platform.
In ZeroNet there is no concept of servers. Thus, server-side languages like PHP or Ruby are not needed. Instead, one can create dynamic content using ZeroNet's API (called ZeroFrame), JavaScript (or CoffeeScript) and the SQL database provided to all websites.
## Tutorials
### ZeroChat tutorial
In this tutorial we are going to build a P2P, decentralized, server-less chat site in less then 100 lines of code.
* [Read on ZeroBlog](http://127.0.0.1:43110/Blog.ZeroNetwork.bit/?Post:99:ZeroChat+tutorial)
* [Read on Medium.com](https://decentralize.today/decentralized-p2p-chat-in-100-lines-of-code-d6e496034cd4)
## Useful Information
### ZeroNet Debug mode
ZeroNet comes with a `--debug` flag that will make site development easier.
To run ZeroNet in debug mode use: `python zeronet.py --debug`
If you are using compiled/bundled version of ZeroNet:
* On Windows: `lib\ZeroNet.cmd --debug`
* On Linux: `./ZeroNet.sh --debug`
* On Mac: `./ZeroNet.app/Contents/MacOS/ZeroNet --debug`
#### Debug mode features:
- Automatic CoffeeScript -> JavaScript conversion (All examples used in this documentation and sample sites are written in [CoffeeScript](http://coffeescript.org/))
- Debug messages will appear in the console
- Auto reload of some source files (UiRequest, UiWebsocket, FileRequest) on modification to prevent restarting (Requires [PyFilesystem](http://pyfilesystem.org/) on GNU/Linux)
- `http://127.0.0.1:43110/Debug` Traceback and interactive Python console at the last error position (using the wonderful Werkzeug debugger - Requires [Werkzeug](http://werkzeug.pocoo.org/))
- `http://127.0.0.1:43110/Console` Spawns an interactive Python console (Requires [Werkzeug](http://werkzeug.pocoo.org/))
### Disable HTTP Browser Caching
In addition to Debug Mode, disabling HTTP Caching in the browser is an essential part of ZeroNet site development. Modern web browsers attempt to cache web content whenever they can. As all ZeroNet sites run in an iframe, web browsers cannot detect when a ZeroNet site's content changes, and thus site changes are often not reflected if HTTP Caching is enabled.
To disable, open your browser's devtools, navigate to the devtools settings and check the option along the lines of 'Disable HTTP Cache (when toolbox is open)'. As the setting suggests, make sure to keep devtools open when testing new changes to your site!
### Extra features (works only for sites that you own)
- Merged CSS files: All CSS files inside the site folder will be merged into one file called `all.css`. You can choose to include only this file to your site. If you want to keep the other CSS files to make the development easier, you can add them to the ignore key of your `content.json`. This way, they won't be published with your site. (eg: add to your `content.json` `"ignore": "(js|css)/(?!all.(js|css))"` this will ignore all CSS and JS files except `all.js` and `all.css`)
- Merged JS files: All JS files inside the site folder will be merged into one file called `all.js`. If a CoffeeScript compiler is present (bundled for Windows) it will convert `.coffee` to `.js`.
- Order in which files are merged into all.css/all.js: Files inside subdirectories of the css/js folder comes first; Files in the css/js folder will be merged according to file name ordering (01_a.css, 02_a.css, etc)
## Need Help?
ZeroNet has a growing community of developers who hang out in various spaces. If you would like to ask for help, advice or just want to hang out, feel free to connect in to the following services:
### Forums
* [ZeroExchange](http://127.0.0.1:43110/zeroexchange.bit/), a p2p StackOverflow clone
* [ZeroTalk](http://127.0.0.1:43110/Talk.ZeroNetwork.bit/), a p2p Reddit-like forum
### Chat
* [#zeronet-dev:matrix.org](https://riot.im/app/#/room/#zeronet-dev:matrix.org) on Matrix
* IRC at #zeronet on Freenode

File diff suppressed because it is too large Load Diff

3
docs/zh/translation.md Normal file
View File

@ -0,0 +1,3 @@
# 如何翻译
Instructions goes here.

View File

@ -0,0 +1,62 @@
# Create new ZeroNet site
## Easy way: Using the web interface
* Click on **⋮** > **"Create new, empty site"** menu item on the site [ZeroHello](http://127.0.0.1:43110/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D).
* You will be **redirected** to a completely new site that is only modifiable by you!
* You can find and modify your site's content in **data/[yoursiteaddress]** directory
* After the modifications open your site, drag the topright "0" button to left, then press **sign** and **publish** buttons on the bottom
## Manual way: Using the command line
### 1. Create site structure
* Shut down ZeroNet if it is running
* Browse to the folder where ZeroNet is installed and run:
```bash
$ zeronet.py siteCreate
...
- Site private key: 23DKQpzxhbVBrAtvLEc2uvk7DZweh4qL3fn3jpM3LgHDczMK2TtYUq
- Site address: 13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2
...
- Site created!
$ zeronet.py
...
```
- This will create the initial files for your site inside ```data/13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2```.
> __Note:__
> Windows users using the bundle version must browse into the ZeroBundle/ZeroNet folder and run `"../Python/python.exe" zeronet.py siteCreate`
### 2. Build/Modify site
* Update the site files located in ```data/[your site address key]``` (eg: 13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2).
* When your site is ready run:
```bash
$ zeronet.py siteSign 13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2
- Signing site: 13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2...
Private key (input hidden):
```
* Enter the private key you got when you created the site. This will sign all files so peers can verify that the site owner is who made the changes.
### 3. Publish site changes
* In order to inform peers about the changes you made you need to run:
```bash
$ zeronet.py sitePublish 13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2
...
Site:13DNDk..bhC2 Publishing to 3/10 peers...
Site:13DNDk..bhC2 Successfuly published to 3 peers
- Serving files....
```
* That's it! You've successfully signed and published your modifications.
* Your site will be accessible from: ```http://localhost:43110/13DNDkMUExRf9Xa9ogwPKqp7zyHFEqbhC2```
**Next steps:** [ZeroNet Developer Documentation](../../site_development/getting_started/)

View File

@ -0,0 +1,42 @@
# Installing ZeroNet
* Download ZeroBundle package: [Microsoft Windows](https://github.com/HelloZeroNet/ZeroNet-win/archive/dist/ZeroNet-win.zip), [Apple macOS](https://github.com/HelloZeroNet/ZeroNet-mac/archive/dist/ZeroNet-mac.zip), [Linux 64bit](https://github.com/HelloZeroNet/ZeroBundle/raw/master/dist/ZeroBundle-linux64.tar.gz), [Linux 32bit](https://github.com/HelloZeroNet/ZeroBundle/raw/master/dist/ZeroBundle-linux32.tar.gz)
* Unpack anywhere
* Run `ZeroNet.exe` (win), `ZeroNet(.app)` (macOS), `ZeroNet.sh` (linux)
### Manual install for Debian Linux
* `sudo apt-get update`
* `sudo apt-get install msgpack-python python-gevent`
* `wget https://github.com/HelloZeroNet/ZeroNet/archive/master.tar.gz`
* `tar xvpfz master.tar.gz`
* `cd ZeroNet-master`
* Start with `python zeronet.py`
* Open http://127.0.0.1:43110/ in your browser
### [Vagrant](https://www.vagrantup.com/)
* `vagrant up`
* Access VM with `vagrant ssh`
* `cd /vagrant`
* Run `python zeronet.py --ui_ip 0.0.0.0`
* Open http://127.0.0.1:43110/ in your browser
### [Docker](https://www.docker.com/)
* `docker run -d -v <local_data_folder>:/root/data -p 15441:15441 -p 127.0.0.1:43110:43110 nofish/zeronet`
* This Docker image includes the Tor proxy, which is disabled by default. Beware that some
hosting providers may not allow you running Tor in their servers. If you want to enable it,
set `ENABLE_TOR` environment variable to `true` (Default: `false`). E.g.:
`docker run -d -e "ENABLE_TOR=true" -v <local_data_folder>:/root/data -p 15441:15441 -p 127.0.0.1:43110:43110 nofish/zeronet`
* Open http://127.0.0.1:43110/ in your browser
### [Virtualenv](https://virtualenv.readthedocs.org/en/latest/)
* `virtualenv env`
* `source env/bin/activate`
* `pip install msgpack-python gevent`
* `python zeronet.py`
* Open http://127.0.0.1:43110/ in your browser

View File

@ -0,0 +1,129 @@
# Sample ZeroNet sites
## ZeroHello
The homepage of ZeroNet
- Lists all added sites: Title, Peer number, Modification date, etc.
- Site actions: Update, Pause, Resume, Delete, Check Files and Save as .zip
- Clone sites to have your own blog / forum
- ZeroNet Statistics
- If an update is available, ZeroNet can be updated with one click
![ZeroHello](../img/zerohello.png)
Address: [1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D](http://127.0.0.1:43110/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D)
[Source code](https://github.com/HelloZeroNet/ZeroHello)
---
## ZeroBlog
Self publishing blog demo
- Inline content editor
- Markdown syntax
- Code syntax highlighting
- Site signing & publishing through the web interface
How does it work?
- `data.json` contained within site files contain blog posts and comments. Each user has their own.
- Upon pressing `Sign & Publish new content`, the blogger is asked for the site private key (displayed when [creating a new site using zeronet.py siteCreate command](create_new_site/))
- Your ZeroNet client signs the new/modified files and publishes directly to other peers
- The site will then be accessible until to other peers to view
![ZeroBlog](../img/zeroblog.png)
Address: [1BLogC9LN4oPDcruNz3qo1ysa133E9AGg8](http://127.0.0.1:43110/1BLogC9LN4oPDcruNz3qo1ysa133E9AGg8) or [blog.zeronetwork.bit](http://127.0.0.1:43110/blog.zeronetwork.bit)
[Source code](https://github.com/HelloZeroNet/ZeroBlog)
---
## ZeroTalk
Decentralized, P2P forum demo
- Post and comment creation, modification, deletion and upvoting
- Commenting and content modifications pushed directly to other peers
- Only you can sign and modify your own files
- Real time display of new comments
How does it work?
- To post and comment you have to request a certificate of registration (a cryptographic sign) from a ZeroID provider
- After you have the certificate you can publish your content (messages, posts, upvotes) directly to other peers
![ZeroTalk](../img/zerotalk.png)
Address: [1TaLkFrMwvbNsooF4ioKAY9EuxTBTjipT](http://127.0.0.1:43110/1TaLkFrMwvbNsooF4ioKAY9EuxTBTjipT) or [talk.zeronetwork.bit](http://127.0.0.1:43110/talk.zeronetwork.bit)
[Source code](https://github.com/HelloZeroNet/ZeroTalk)
---
## ZeroMail
End-to-end encrypted, distributed, P2P messaging site. To improve privacy it uses a BitMessage-like solution and will not expose the message recipient.
- Using ECIES for secret exchange, AES256 for message encoding
- When you first visit the site, it adds your public key to your data file. At that point anyone is able to send a message to you
- Everyone tries to decrypt every message, this improves privacy by making it impossible to find the message recipient
- To reduce per message overhead and increase decryption speed, we re-use the AES key, but a new IV is generated every time
![ZeroTalk](../img/zeromail.png)
Address: [1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27](http://127.0.0.1:43110/1MaiL5gfBM1cyb4a8e3iiL8L5gXmoAJu27) or [mail.zeronetwork.bit](http://127.0.0.1:43110/mail.zeronetwork.bit)
[Source code](https://github.com/HelloZeroNet/ZeroMail)
---
## ZeroMe
Decentralized, Twitter-like P2P social network.
- Stores user information in ZeroMe user registry
- Stores posts and comments in MergerSites called Hubs
- Upload images as optional files
- Real time display of feed activity
![ZeroMe](../img/zerome.png)
Address: [1MeFqFfFFGQfa1J3gJyYYUvb5Lksczq7nH](http://127.0.0.1:43110/1MeFqFfFFGQfa1J3gJyYYUvb5Lksczq7nH)
[Source code](https://github.com/HelloZeroNet/ZeroMe)
---
## ReactionGIFs
Demo for optional files, files which only download from other peers if your browser requests them.
![ReactionGIFs](../img/reactiongifs.jpg)
Address: [1Gif7PqWTzVWDQ42Mo7np3zXmGAo3DXc7h](http://127.0.0.1:43110/1Gif7PqWTzVWDQ42Mo7np3zXmGAo3DXc7h)
[Source code](https://github.com/HelloZeroNet/ReactionGIFs)
---
## ZeroChat
The finished site for the tutorial of creating a server-less, SQL backed, real-time updated P2P chat application using ZeroNet in less than 100 lines of code.
- Uses ZeroID certificate for authentication
- Stores messages in a SQLite database
- Posts messages and distribute directly to other users in real-time
- Real-time update the messages as they arrive
![ZeroChat](../img/zerochat.png)
Address of finished site: [1AvF5TpcaamRNtqvN1cnDEWzNmUtD47Npg](http://127.0.0.1:43110/1AvF5TpcaamRNtqvN1cnDEWzNmUtD47Npg)
Tutorial on ZeroBlog:
[Part1](http://127.0.0.1:43110/Blog.ZeroNetwork.bit/?Post:43:ZeroNet+site+development+tutorial+1),
[Part2](http://127.0.0.1:43110/Blog.ZeroNetwork.bit/?Post:46:ZeroNet+site+development+tutorial+2)

54
mkdocs-zh.yml Normal file
View File

@ -0,0 +1,54 @@
site_name: ZeroNet
site_url: https://zeronet.io
site_description: 使用比特币加密技术与BitTorrent的分布式网络
repo_url: https://github.com/HelloZeroNet/ZeroNet
edit_uri: ../Documentation/edit/master/docs/zh/
extra_css: [docs.css, stylesheets/menu.css]
extra_javascript: [ZeroFrame.js, jquery.min.js, docs.js, javascripts/menu.js]
docs_dir: docs/zh
site_dir: site
theme:
language: 'zh'
feature:
tabs: true
palette:
primary: "deep purple"
accent: "deep purple"
logo: "logo/zeronet_logo.svg"
name: "material"
favicon: "logo/favicon.ico"
custom_dir: "docs/resources"
font: false
markdown_extensions:
- toc:
permalink: true
- codehilite
plugins:
- search:
lang: ['en']
nav:
- 概述: "index.md"
- 常见问题: "faq.md"
- 开始使用ZeroNet:
- "using_zeronet/installing.md"
- "using_zeronet/sample_sites.md"
- "using_zeronet/create_new_site.md"
- 网站开发:
- "site_development/getting_started.md"
- "site_development/zeroframe_api_reference.md"
- "site_development/content_json.md"
- "site_development/dbschema_json.md"
- "site_development/cert_authority.md"
- 帮助开发ZeroNet:
- "help_zeronet/contributing.md"
- "help_zeronet/coding_conventions.md"
- "help_zeronet/network_protocol.md"
- "help_zeronet/donate.md"