aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/about/about_hubzilla.bb11
-rw-r--r--doc/admin/administrator_guide.md19
-rw-r--r--doc/developer/api_zot.bb749
-rw-r--r--doc/developer/zot_protocol.bb479
-rw-r--r--doc/hook/stream_item.bb13
-rw-r--r--doc/hook/zot_best_algorithm.bb3
-rw-r--r--doc/hooklist.bb6
-rw-r--r--doc/member/assets/qr_text_to_post.pngbin0 -> 273 bytes
-rw-r--r--doc/member/assets/zat_dialog.pngbin0 -> 81837 bytes
-rw-r--r--doc/member/bbcode.html316
-rw-r--r--doc/member/member_guide.bb458
-rw-r--r--doc/roadmap_hz3.md27
-rw-r--r--doc/toc.html31
13 files changed, 2095 insertions, 17 deletions
diff --git a/doc/about/about_hubzilla.bb b/doc/about/about_hubzilla.bb
index f249df66f..3327e0b50 100644
--- a/doc/about/about_hubzilla.bb
+++ b/doc/about/about_hubzilla.bb
@@ -32,7 +32,7 @@ The $Projectname software stack is a relatively standard webserver application w
[*= nomadic identity] The ability to authenticate and easily migrate an identity across independent hubs and web domains. Nomadic identity provides true ownership of an online identity, because the identities of the channels controlled by an account on a hub are not tied to the hub itself. A hub is more like a "host" for channels. With Hubzilla, you don't have an "account" on a server like you do on typical websites; you own an identity that you can take with you across the grid by using clones.
-[*= [url=[baseurl]/help/developer/what_is_zot]Zot[/url]] The novel JSON-based protocol for implementing secure decentralised communications and services. It differs from many other communication protocols by building communications on top of a decentralised identity and authentication framework. The authentication component is similar to OpenID conceptually but is insulated from DNS-based identities. Where possible remote authentication is silent and invisible. This provides a mechanism for internet-scale distributed access control which is unobtrusive.
+[*= [url=[baseurl]/help/developer/api_zot]Zot[/url]] The novel JSON-based protocol for implementing secure decentralised communications and services. It differs from many other communication protocols by building communications on top of a decentralised identity and authentication framework. The authentication component is similar to OpenID conceptually but is insulated from DNS-based identities. Where possible remote authentication is silent and invisible. This provides a mechanism for internet-scale distributed access control which is unobtrusive.
[/dl]
[h3]Features[/h3]
@@ -186,17 +186,8 @@ Any number of profiles may be created containing different information and these
$Projectname offers a simple, one-click account backup, where you can download a complete backup of your profile(s). Backups can then be used to clone or restore a profile.
[h4]Account Deletion[/h4]
-
Accounts can be immediately deleted by clicking on a link. That's it. All associated content is then deleted from the grid (this includes posts and any other content produced by the deleted profile). Depending on the number of connections you have, the process of deleting remote content could take some time but it is scheduled to happen as quickly as is practical.
-[h4]Content Creation[/h4]
-
-[h4]Writing Posts[/h4]
-
-$Projectname supports a number of different ways of adding rich-text content. The default is a custom variant of BBcode, tailored for use in $Projectname. You may also enable the use of Markdown if you find that easier to work with. A visual editor may also be used. The traditional visual editor for $Projectname had some serious issues and has since been removed. We are currently looking for a replacement.
-
-When creating "Websites", content may be entered in HTML, Markdown, BBcode, and/or plain text.
-
[h4]Deletion of content[/h4]
Any content created in $Projectname remains under the control of the member (or channel) that originally created it. At any time, a member can delete a message, or a range of messages. The deletion process ensures that the content is deleted, regardless of whether it was posted on a channel's primary (home) hub, or on another hub, where the channel was remotely authenticated via Zot ($Projectname communication and authentication protocol).
diff --git a/doc/admin/administrator_guide.md b/doc/admin/administrator_guide.md
index b7056e7e3..f21c55327 100644
--- a/doc/admin/administrator_guide.md
+++ b/doc/admin/administrator_guide.md
@@ -308,8 +308,16 @@ empty:
1. On the $Projectname server visit new.hub/locs and upgrade to your channel to a primary one. And when the old Redmatrix server is still listed delete them here as well. Press "Sync" to inform all other server in the grid.
### Troubleshooting
+
#### Log files
+The system logfile is an extremely useful resource for tracking down things that go wrong. This can be enabled in the admin/log configuration page. A loglevel setting of LOGGER_DEBUG is preferred for stable production sites. Most things that go wrong with communications or storage are listed here. A setting of LOGGER_DATA provides [b]much[/b] more detail, but may fill your disk. In either case we recommend the use of logrotate on your operating system to cycle logs and discard older entries.
+
+At the bottom of your .htconfig.php file are several lines (commented out) which enable PHP error logging. This reports issues with code syntax and executing the code and is the first place you should look for issues which result in a "white screen" or blank page. This is typically the result of code/syntax problems.
+Database errors are reported to the system logfile, but we've found it useful to have a file in your top-level directory called dbfail.out which [b]only[/b] collects database related issues. If the file exists and is writable, database errors will be logged to it as well as to the system logfile.
+
+In the case of "500" errors, the issues may often be logged in your webserver logs, often /var/log/apache2/error.log or something similar. Consult your operating system documentation.
+
There are three different log facilities.
**The first is the database failure log**. This is only used if you create a file called specifically 'dbfail.out' in the root folder of your website and make it write-able by the web server. If we have any database failed queries, they are all reported here. They generally indicate typos in our queries, but also occur if the database server disconnects or tables get corrupted. On rare occasions we'll see race conditions in here where two processes tried to create an xchan or cache entry with the same ID. Any other errors (especially persistent errors) should be investigated.
@@ -343,3 +351,14 @@ To immediately clear out all the extra logging stuff you added. Use the informa
1. Enable the **logrot** addon in the official [hubzilla-addons](https://github.com/redmatrix/hubzilla-addons) repo
1. Create a directory in your web root called `log` with webserver write permissions
1. Go to the **logrot** admin settings and enter this folder name as well as the max size and number of retained log files.
+
+
+#### Reporting issues
+
+When reporting issues, please try to provide as much detail as may be necessary for developers to reproduce the issue and provide the complete text of all error messages.
+
+We encourage you to try to the best of your abilities to use these logs combined with the source code in your possession to troubleshoot issues and find their cause. The community is often able to help, but only you have access to your site logfiles and it is considered a security risk to share them.
+
+If a code issue has been uncovered, please report it on the project bugtracker (https://github.com/redmatrix/hubzilla/issues). Again provide as much detail as possible to avoid us going back and forth asking questions about your configuration or how to duplicate the problem, so that we can get right to the problem and figure out what to do about it. You are also welcome to offer your own solutions and submit patches. In fact we encourage this as we are all volunteers and have little spare time available. The more people that help, the easier the workload for everybody. It's OK if your solution isn't perfect. Every little bit helps and perhaps we can improve on it.
+
+
diff --git a/doc/developer/api_zot.bb b/doc/developer/api_zot.bb
new file mode 100644
index 000000000..f33faed17
--- /dev/null
+++ b/doc/developer/api_zot.bb
@@ -0,0 +1,749 @@
+[h3]Zot API[/h3]
+
+The API endpoints detailed below are relative to [code]api/z/1.0[/code], meaning that if an API is listed as [code]channel/stream[/code] the full API URL is [code][baseurl]/api/z/1.0/channel/stream[/code].
+
+[h3]channel/export/basic[/h3]
+
+Export channel data
+
+
+[h3]channel/stream[/h3]
+
+Fetch channel conversation items
+
+[h3]network/stream[/h3]
+
+
+Fetch network conversation items
+
+
+
+[h3]files[/h3]
+
+
+List file storage (attach DB)
+
+GET /api/z/1.0/files
+
+
+Options:
+
+ - hash
+ return only entries matching hash (exactly)
+
+ - filename
+ return only entries matching filename (substring)
+
+ - filetype
+ return only entries matching filetype/mimetype (substring)
+
+ - start
+ start at record (default 0)
+
+ - records
+ number of records to return or 0 for unlimited
+
+
+
+Example:
+
+curl -u mychannel:mypassword https://xyz.macgirvin.com/api/z/1.0/files -d filetype=multipart/mixed
+
+
+Returns:
+[code nowrap]
+ {
+
+ "success": true,
+ "results": [
+ {
+ "id": "1",
+ "aid": "1",
+ "uid": "2",
+ "hash": "44ee8b2a1a7f36dea07b93b7747a2383a1bc0fdd08339e8928bfcbe45f65d939",
+ "filename": "Profile Photos",
+ "filetype": "multipart/mixed",
+ "filesize": "0",
+ "revision": "0",
+ "folder": "",
+ "os_storage": "1",
+ "is_dir": "1",
+ "is_photo": "0",
+ "flags": "0",
+ "created": "2016-01-02 21:51:17",
+ "edited": "2016-01-02 21:51:17",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": ""
+ },
+ {
+ "id": "12",
+ "aid": "1",
+ "uid": "2",
+ "hash": "71883f1fc64af33889229cbc79c5a056deeec5fc277d765f182f19073e1b2998",
+ "filename": "Cover Photos",
+ "filetype": "multipart/mixed",
+ "filesize": "0",
+ "revision": "0",
+ "folder": "",
+ "os_storage": "1",
+ "is_dir": "1",
+ "is_photo": "0",
+ "flags": "0",
+ "created": "2016-01-15 00:24:33",
+ "edited": "2016-01-15 00:24:33",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": ""
+ },
+ {
+ "id": "16",
+ "aid": "1",
+ "uid": "2",
+ "hash": "f48f7ec3278499d1dd86b72c3207beaaf4717b07df5cc9b373f14d7aad2e1bcd",
+ "filename": "2016-01",
+ "filetype": "multipart/mixed",
+ "filesize": "0",
+ "revision": "0",
+ "folder": "",
+ "os_storage": "1",
+ "is_dir": "1",
+ "is_photo": "0",
+ "flags": "0",
+ "created": "2016-01-22 03:24:55",
+ "edited": "2016-01-22 03:26:57",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": ""
+ }
+ ]
+ }
+[/code]
+
+
+
+[h3]filemeta[/h3]
+
+Export file metadata for any uploaded file
+
+
+[h3]filedata[/h3]
+
+
+Provides the ability to download a file from cloud storage in chunks
+
+GET /api/z/1.0/filedata
+
+
+Required:
+
+ - file_id
+ attach.hash of desired file ('begins with' match)
+
+
+Optional:
+
+ - start
+ starting byte of returned data in file (counting from 0)
+
+ - length
+ length (prior to base64 encoding) of chunk to download
+
+
+Returns:
+
+ attach (DB) structure with base64 encoded 'content' comprised of the desired chunk
+
+
+
+Example:
+
+ https://xyz.macgirvin.com/api/z/1.0/filedata?f=&file_id=9f5217770fd&start=0&length=48
+
+Returns:
+[code nowrap]
+ {
+
+ "attach": {
+ "id": "107",
+ "aid": "1",
+ "uid": "2",
+ "hash": "9f5217770fd55d563bd77f84d534d8e119a187514bbd391714626cd9c0e60207",
+ "creator": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "filename": "pcxtopbm.c",
+ "filetype": "application/octet-stream",
+ "filesize": "3934",
+ "revision": "0",
+ "folder": "",
+ "flags": "0",
+ "is_dir": "0",
+ "is_photo": "0",
+ "os_storage": "1",
+ "os_path": "",
+ "display_path": "",
+ "content": "LyogcGN4dG9wYm0uYyAtIGNvbnZlcnQgUEMgcGFpbnRicnVzaCAoLnBjeCkgZmls",
+ "created": "2016-07-24 23:13:01",
+ "edited": "2016-07-24 23:13:01",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": "",
+ "start": 0,
+ "length": 48
+ }
+
+ }
+[/code]
+
+[h3]file/export[/h3]
+
+
+[h3]file[/h3]
+
+
+[h3]albums[/h3]
+
+
+Description: list photo albums
+
+GET /api/z/1.0/albums
+
+
+Output:
+
+ text - textual name
+
+ total - number of photos in this album
+
+ url - web URL
+
+ urlencode - textual name, urlencoded
+
+ bin2hex - textual name using bin2hex (which is used in the web URL link)
+
+
+Example:
+
+[code nowrap]
+ {
+
+ "success": true,
+ "albums": [
+ {
+ "text": "/",
+ "total": "2",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/",
+ "urlencode": "",
+ "bin2hex": ""
+ },
+ {
+ "text": "2016-01",
+ "total": "6",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/323031362d3031",
+ "urlencode": "2016-01",
+ "bin2hex": "323031362d3031"
+ },
+ {
+ "text": "2016-02",
+ "total": "7",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/323031362d3032",
+ "urlencode": "2016-02",
+ "bin2hex": "323031362d3032"
+ },
+ {
+ "text": "Cover Photos",
+ "total": "5",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/436f7665722050686f746f73",
+ "urlencode": "Cover+Photos",
+ "bin2hex": "436f7665722050686f746f73"
+ },
+ {
+ "text": "Profile Photos",
+ "total": "26",
+ "url": "https://xyz.macgirvin.com/photos/hubzilla/album/50726f66696c652050686f746f73",
+ "urlencode": "Profile+Photos",
+ "bin2hex": "50726f66696c652050686f746f73"
+ }
+ ]
+
+ }
+[/code]
+
+
+[h3]photos[/h3]
+
+
+list photo metadata
+
+
+[h3]photo[/h3]
+
+
+
+[h3]group[/h3]
+
+
+`GET /api/z/1.0/group`
+
+Description: list privacy groups
+
+Returns: DB tables of all privacy groups.
+
+To use with API group_members, provide either 'group_id' from the id element returned in this call, or 'group_name' from the gname returned in this call.
+
+[code nowrap]
+ [
+
+ {
+ "id": "1",
+ "hash": "966c946394f3e2627bbb8a55026b5725e582407098415c02f85232de3f3fde76Friends",
+ "uid": "2",
+ "visible": "0",
+ "deleted": "0",
+ "gname": "Friends"
+ },
+ {
+ "id": "2",
+ "hash": "852ebc17f8c3ed4866f2162e384ded0f9b9d1048f93822c0c84196745f6eec66Family",
+ "uid": "2",
+ "visible": "1",
+ "deleted": "0",
+ "gname": "Family"
+ },
+ {
+ "id": "3",
+ "hash": "cc3cb5a7f9818effd7c7c80a58b09a189b62efa698a74319117babe33ee30ab9Co-workers",
+ "uid": "2",
+ "visible": "0",
+ "deleted": "0",
+ "gname": "Co-workers"
+ }
+ ]
+[/code]
+[h3]group_members[/h3]
+
+
+`GET /api/z/1.0/group_members`
+
+Required:
+
+group_id or group_name
+
+
+Returns:
+
+group_member+abook+xchan (DB join) for each member of the privacy group
+
+[code nowrap]
+ [
+
+ {
+ "id": "1",
+ "uid": "2",
+ "gid": "1",
+ "xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "abook_id": "2",
+ "abook_account": "1",
+ "abook_channel": "2",
+ "abook_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "abook_my_perms": "218555",
+ "abook_their_perms": "0",
+ "abook_closeness": "0",
+ "abook_created": "2016-01-02 21:16:26",
+ "abook_updated": "2016-01-02 21:16:26",
+ "abook_connected": "0000-00-00 00:00:00",
+ "abook_dob": "0000-00-00 00:00:00",
+ "abook_flags": "0",
+ "abook_blocked": "0",
+ "abook_ignored": "0",
+ "abook_hidden": "0",
+ "abook_archived": "0",
+ "abook_pending": "0",
+ "abook_unconnected": "0",
+ "abook_self": "1",
+ "abook_feed": "0",
+ "abook_profile": "",
+ "abook_incl": "",
+ "abook_excl": "",
+ "abook_instance": "",
+ "xchan_hash": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "xchan_guid": "lql-1VnxtiO4-WF0h72wLX1Fu8szzHDOXgQaTbELwXW77k8AKFfh-hYr70vqMrc3SSvWN-Flrc5HFhRTWB7ICw",
+ "xchan_guid_sig": "PafvEL0VpKfxATxlCqDjfOeSIMdmpr3iU7X-Sysa1h5LzDpjSXsjO37tYZL-accb1M5itLlfnW5epkTa5I4flsW21zSY1A2jCuBQUTLLGV7rNyyBy7lgqJUFvAMRx0TfXzP9lcaPqlM9T1tA6jfWOsOmkdzwofGeXBnsjGfjsO2xdGYe6vwjOU0DSavukvzDMnOayB9DekpvDnaNBTxeGLM45Skzr7ZEMcNF7TeXMbnvpfLaALYEKeQs9bGH-UgAG8fBWgzVAzeBfx_XSR1rdixjyiZGP0kq0h35SlmMPcEjliodOBFwMXqpXFB7Ibp4F6o6te2p2ErViJccQVG8VNKB6SbKNXY6bhP5zVcVsJ-vR-p4xXoYJJvzTN7yTDsGAXHOLF4ZrXbo5yi5gFAlIrTLAF2EdWQwxSGyLRWKxG8PrDkzEzX6cJJ0VRcLh5z6OI5QqQNdeghPZbshMFMJSc_ApCPi9_hI4ZfctCIOi3T6bdgTNKryLm5fhy_eqjwLAZTGP-aUBgLZpb1mf2UojBn6Ey9cCyq-0T2RWyk-FcIcbV4qJ-p_8oODqw13Qs5FYkjLr1bGBq82SuolkYrXEwQClxnrfKa4KYc2_eHAXPL01iS9zVnI1ySOCNJshB97Odpooc4wk7Nb2Fo-Q6THU9zuu0uK_-JbK7IIl6go2qA",
+ "xchan_pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA18JB76lyP4zzL/y7BCej\neJnfZIWZNtM3MZvI1zEVMWmmwOS+u/yH8oPwyaDk4Y/tnj8GzMPj1lCGVRcd8EJa\nNrCMd50HODA5EsJtxpsOzRcILYjOcTtIAG1K4LtKqELi9ICAaFp0fNfa+Jf0eCek\nvPusx2/ORhy+o23hFoSMhL86o2gmaiRnmnA3Vz4ZMG92ieJEDMXt9IA1EkIqS4y5\nBPZfVPLD1pv8iivj+dtN1XjwplgjUbtxmU0/Ej808nHppscRIqx/XJ0XZU90oNGw\n/wYoK2EzJlPbRsAkwNqoFrAYlr5HPpn4BJ2ebFYQgWBUraD7HwS5atsQEaxGfO21\nlUP0+lDg9t3CXvudDj0UG1jiEKbVIGA+4aG0GN2DSC5AyRq/GRxqyay5W2vQbAZH\nyvxPGrZFO24I65g3pjhpjEsLqZ4ilTLQoLMs0drCIcRm5RxMUo4s/LMg16lT4cEk\n1qRtk2X0Sb1AMQQ2uRXiVtWz77QHMONEYkf6OW4SHbwcv5umvlv69NYEGfCcbgq0\nAV7U4/BWztUz/SWj4r194CG43I9I8dmaEx9CFA/XMePIAXQUuABfe1QMOR6IxLpq\nTHG1peZgHQKeGz4aSGrhQkZNNoOVNaZoIfcvopxcHDTZLigseEIaPPha4WFYoKPi\nUPbZ5o8gTLc750uzrnb2jwcCAwEAAQ==\n-----END PUBLIC KEY-----\n",
+ "xchan_photo_mimetype": "image/png",
+ "xchan_photo_l": "https://xyz.macgirvin.com/photo/profile/l/2",
+ "xchan_photo_m": "https://xyz.macgirvin.com/photo/profile/m/2",
+ "xchan_photo_s": "https://xyz.macgirvin.com/photo/profile/s/2",
+ "xchan_addr": "teller@xyz.macgirvin.com",
+ "xchan_url": "https://xyz.macgirvin.com/channel/teller",
+ "xchan_connurl": "https://xyz.macgirvin.com/poco/teller",
+ "xchan_follow": "https://xyz.macgirvin.com/follow?f=&url=%s",
+ "xchan_connpage": "",
+ "xchan_name": "Teller",
+ "xchan_network": "zot",
+ "xchan_instance_url": "",
+ "xchan_flags": "0",
+ "xchan_photo_date": "2016-10-19 01:26:50",
+ "xchan_name_date": "2016-01-02 21:16:26",
+ "xchan_hidden": "0",
+ "xchan_orphan": "0",
+ "xchan_censored": "0",
+ "xchan_selfcensored": "0",
+ "xchan_system": "0",
+ "xchan_pubforum": "0",
+ "xchan_deleted": "0"
+ },
+ {
+ "id": "12",
+ "uid": "2",
+ "gid": "1",
+ "xchan": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
+ "abook_id": "24",
+ "abook_account": "1",
+ "abook_channel": "2",
+ "abook_xchan": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
+ "abook_my_perms": "218555",
+ "abook_their_perms": "218555",
+ "abook_closeness": "80",
+ "abook_created": "2016-01-27 00:48:43",
+ "abook_updated": "2016-12-04 17:16:58",
+ "abook_connected": "2016-12-04 17:16:58",
+ "abook_dob": "0001-01-01 00:00:00",
+ "abook_flags": "0",
+ "abook_blocked": "0",
+ "abook_ignored": "0",
+ "abook_hidden": "0",
+ "abook_archived": "0",
+ "abook_pending": "0",
+ "abook_unconnected": "0",
+ "abook_self": "0",
+ "abook_feed": "0",
+ "abook_profile": "debb5236efb1626cfbad33ccb49892801e5f844aa04bf81f580cfa7d13204819",
+ "abook_incl": "",
+ "abook_excl": "",
+ "abook_instance": "",
+ "xchan_hash": "xuSMUYxw1djBB97qXsbrBN1nzJH_gFwQL6pS4zIy8fuusOfBxNlMiVb4h_q5tOEvpE7tYf1EsryjNciMuPIj5w",
+ "xchan_guid": "d5EMLlt1tHHZ0dANoA7B5Wq9UgXoWcFS9-gXOkL_AAejcPApoQRyxfHTuu8DoTbUaO-bYmX5HPuWuK9PHyqNmA",
+ "xchan_guid_sig": "CVWEMRPtzI1YcHfnnWHTuv3H964OAmSElgUfxMoX6RdQdxNpqb_POirpVuyP8s3W17mVCfO5V9IAjkg5iKcqCk6YcvOD_egmMy-AnM9TC1kKndQHw55CunD82Q8K_xBNSXkSROizcNkKh9DVLjJPFjW1AqtI4njkZ3EMgrWqnbFRM1qPToUoCY9zM3tEMHoAD9YX1zP90wl40LzfN-dtcNWpSBbiz9owou62uzLbN7mrCwKOMlXLjwwGswRnxIsEnb3O-FXOs8hs0mArKe9snq1-BKeD16LyzxgwlpVLElzIJZGEZGtMdIJgeRzKuBvPjsOIpQ1yAkuOpFJ3nGCM-IPOIIjAmyVl5zD3xPVcxxpZlJRn5fG1Y-gnqTgsrEQCA7M6XPWQdrdHU4akZfyUyFJDhv3uM-jon9VzrYTBw68R0WA-1Z8WafEHA4qh5OWAj85lUarwhr7iTiEckH51ypPCPs6VbT6Pw7yMaxfjFOcipashQagx0tfOlDhE5dQANOXKASFtH1J9-CZY2MQdLPQ6u54d5whuHKMGaJ0V68pnmZ2rOn7g344Ah2WCJrm17jj60QsRMorqRFj7GMdPIA1XB8Wrk88MuYOe3Dhyuu6ZWKI7YTWJS690ZVkKUqAiNHqj0W86DtaiPUc_mmGR0fHl4Gksnko3WmCFv9q2X2E",
+ "xchan_pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoj2xCJktBA8Ww7Hp+ZNL\nrNuQpo8UB/bfvRkIy+yua3xpF1TuXcnAH61kyRz8vXgOu/l2CyxQbIoaGslCV5Sy\n8JKeNXe+IilUdSSEjMIwCPfSPsYnMHsSnHWmPmclvJwEtQUKOZmW5mMuVBvXy7D2\njomFwc69AYphdyys6eQ7Dcn6+FRBiQbyMprZ5lxyVW+O4DuXVNa3ej2ebx0gCJZ4\ntTIlBoKwEey91dY+FyKVFjdwfNczpmL7LgmZXqcVx+MG3mYgibwdVMiXVj5X06cs\nV9hJ5Xi+Aklsv/UWJtjw9FVt7y9TLptnhh4Ra6T/MDmnBBIAkOR7P/X8cRv078MT\nl0IMsP0RJcDEtTLtwHFVtDs6p52KDFqclKWbqmxmxqV3OTPVYtArRGIzgnJi/5ur\nHRr5G6Cif7QY3UowsIOf78Qvy28LwSbdymgBAWwPPKIviXWxGO+9kMWdmPSUQrWy\nK0+7YA9P9fBUFfn9Hc+p8SJQmQ6OAqLwrDGiPSOlGaNrbEqwqLGgIpXwK+lEFcFJ\n3SPOjJRWdR2whlMxvpwX+39+H7dWN3vSa3Al4/Sq7qW8yW2rYwf+eGyp4Z0lRR+8\nJxFMCwZkSw5g14YdlikAPojv5V1c6KuA5ieg8G1hwyONV7A4JHPyEdPt0W0TZi6C\nCOVkPaC3xGrguETZpJfVpwUCAwEAAQ==\n-----END PUBLIC KEY-----\n",
+ "xchan_photo_mimetype": "image/png",
+ "xchan_photo_l": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-4",
+ "xchan_photo_m": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-5",
+ "xchan_photo_s": "https://xyz.macgirvin.com/photo/9da63aa910ea14e1501ee1a749d181a6-6",
+ "xchan_addr": "cloner@xyz.macgirvin.com",
+ "xchan_url": "http://abc.macgirvin.com/channel/cloner",
+ "xchan_connurl": "http://abc.macgirvin.com/poco/cloner",
+ "xchan_follow": "https://xyz.macgirvin.com/follow?f=&url=%s",
+ "xchan_connpage": "",
+ "xchan_name": "Karen",
+ "xchan_network": "zot",
+ "xchan_instance_url": "",
+ "xchan_flags": "0",
+ "xchan_photo_date": "2016-03-31 19:59:20",
+ "xchan_name_date": "2016-01-26 23:23:42",
+ "xchan_hidden": "0",
+ "xchan_orphan": "0",
+ "xchan_censored": "0",
+ "xchan_selfcensored": "0",
+ "xchan_system": "0",
+ "xchan_pubforum": "0",
+ "xchan_deleted": "0"
+ }
+
+ ]
+[/code]
+
+[h3]xchan[/h3]
+
+
+An xchan is a global location independent channel and is the primary record for a network
+identity. It may refer to channels on other websites, networks, or services.
+
+`GET /api/z/1.0/xchan`
+
+Required: one of [ address, hash, guid ] as GET parameters
+
+Returns a portable xchan structure
+
+Example: https://xyz.macgirvin.com/api/z/1.0/xchan?f=&address=mike@macgirvin.com
+
+Returns:
+[code nowrap]
+ {
+ "hash": "jr54M_y2l5NgHX5wBvP0KqWcAHuW23p1ld-6Vn63_pGTZklrI36LF8vUHMSKJMD8xzzkz7s2xxCx4-BOLNPaVA",
+ "guid": "sebQ-IC4rmFn9d9iu17m4BXO-kHuNutWo2ySjeV2SIW1LzksUkss12xVo3m3fykYxN5HMcc7gUZVYv26asx-Pg",
+ "guid_sig": "Llenlbl4zHo6-g4sa63MlQmTP5dRCrsPmXHHFmoCHG63BLq5CUZJRLS1vRrrr_MNxr7zob_Ykt_m5xPKe5H0_i4pDj-UdP8dPZqH2fqhhx00kuYL4YUMJ8gRr5eO17vsZQ3XxTcyKewtgeW0j7ytwMp6-hFVUx_Cq08MrXas429ZrjzaEwgTfxGnbgeQYQ0R5EXpHpEmoERnZx77VaEahftmdjAUx9R4YKAp13pGYadJOX5xnLfqofHQD8DyRHWeMJ4G1OfWPSOlXfRayrV_jhnFlZjMU7vOdQwHoCMoR5TFsRsHuzd-qepbvo3pzvQZRWnTNu6oPucgbf94p13QbalYRpBXKOxdTXJrGdESNhGvhtaZnpT9c1QVqC46jdfP0LOX2xrVdbvvG2JMWFv7XJUVjLSk_yjzY6or2VD4V6ztYcjpCi9d_WoNHruoxro_br1YO3KatySxJs-LQ7SOkQI60FpysfbphNyvYMkotwUFI59G08IGKTMu3-GPnV1wp7NOQD1yzJbGGEGSEEysmEP0SO9vnN45kp3MiqbffBGc1r4_YM4e7DPmqOGM94qksOcLOJk1HNESw2dQYWxWQTBXPfOJT6jW9_crGLMEOsZ3Jcss0XS9KzBUA2p_9osvvhUKuKXbNztqH0oZIWlg37FEVsDs_hUwUJpv2Ar09k4",
+ "pubkey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7QCwvuEIwCHjhjbpz3Oc\ntyei/Pz9nDksNbsc44Cm8jxYGMXsTPFXDZYCcCB5rcAhPPdZSlzaPkv4vPVcMIrw\n5cdX0tvbwa3rNTng6uFE7qkt15D3YCTkwF0Y9FVZiZ2Ko+G23QeBt9wqb9dlDN1d\nuPmu9BLYXIT/JXoBwf0vjIPFM9WBi5W/EHGaiuqw7lt0qI7zDGw77yO5yehKE4cu\n7dt3SakrXphL70LGiZh2XGoLg9Gmpz98t+gvPAUEotAJxIUqnoiTA8jlxoiQjeRK\nHlJkwMOGmRNPS33awPos0kcSxAywuBbh2X3aSqUMjcbE4cGJ++/13zoa6RUZRObC\nZnaLYJxqYBh13/N8SfH7d005hecDxWnoYXeYuuMeT3a2hV0J84ztkJX5OoxIwk7S\nWmvBq4+m66usn6LNL+p5IAcs93KbvOxxrjtQrzohBXc6+elfLVSQ1Rr9g5xbgpub\npSc+hvzbB6p0tleDRzwAy9X16NI4DYiTj4nkmVjigNo9v2VPnAle5zSam86eiYLO\nt2u9YRqysMLPKevNdj3CIvst+BaGGQONlQalRdIcq8Lin+BhuX+1TBgqyav4XD9K\nd+JHMb1aBk/rFLI9/f2S3BJ1XqpbjXz7AbYlaCwKiJ836+HS8PmLKxwVOnpLMbfH\nPYM8k83Lip4bEKIyAuf02qkCAwEAAQ==\n-----END PUBLIC KEY-----\n",
+ "photo_mimetype": "image/jpeg",
+ "photo_l": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-4",
+ "photo_m": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-5",
+ "photo_s": "https://xyz.macgirvin.com/photo/350b74555c04429148f2e12775f6c403-6",
+ "address": "mike@macgirvin.com",
+ "url": "https://macgirvin.com/channel/mike",
+ "connurl": "https://macgirvin.com/poco/mike",
+ "follow": "https://macgirvin.com/follow?f=&url=%s",
+ "connpage": "https://macgirvin.com/connect/mike",
+ "name": "Mike Macgirvin",
+ "network": "zot",
+ "instance_url": "",
+ "flags": "0",
+ "photo_date": "2012-12-06 05:06:11",
+ "name_date": "2012-12-06 04:59:13",
+ "hidden": "1",
+ "orphan": "0",
+ "censored": "0",
+ "selfcensored": "0",
+ "system": "0",
+ "pubforum": "0",
+ "deleted": "0"
+ }
+[/code]
+[h3]item/update[/h3]
+
+
+Create or update an item (post, activity, webpage, etc.)
+
+Usage: `POST /api/z/1.0/item/update`
+
+Description: item/update posts an item (typically a conversation item or post, but can be any item) using form input.
+
+
+Required:
+
+- body
+
+ text/bbcode contents by default.
+
+
+Optional:
+
+- $_FILES['media']
+
+ uploaded media file to include with post
+
+- title
+
+ title of post/item
+
+- contact_allow
+
+ array of xchan.xchan_hash allowed to view this item
+
+- group_allow
+
+ array of group.hash allowed to view this item
+
+- contact_deny
+
+ array of xchan.xchan_hash not allowed to view this item
+
+- group_deny
+
+ array of group.hash not allowed to view this item
+
+- coord
+
+ geographic coordinates
+
+- location
+
+ freefrom location
+
+- expire
+
+ datetime this post will expire or be removed
+
+- mimetype
+
+ mimetype if not text/bbcode
+
+- parent
+
+ item.id of parent to this post (makes it a comment)
+
+- parent_mid
+
+ alternate form of parent using message_id
+
+- remote_xchan
+
+ xchan.xchan_hash of this message author if not the channel owner
+
+- consensus
+
+ boolean set to true if this is a consensus or voting item (default false)
+
+- nocomment
+
+ boolean set to true if comments are to be disabled (default false)
+
+- origin
+
+ do not use this without reading the code
+
+- namespace
+
+ persistent identity for a remote network or service
+
+- remote_id
+
+ message_id of this resource on a remote network or service
+
+- message_id
+
+ message_id of this item (leave unset to generate one)
+
+- created
+
+ datetime of message creation
+
+- post_id
+
+ existing item.id if this is an edit operation
+
+- app
+
+ application or network name to display with item
+
+- categories
+
+ comma separated categories for this item
+
+- webpage
+
+ item.page_type if not 0
+
+- pagetitle
+
+ for webpage and design elements, the 'page name'
+
+- layout_mid
+
+ item.mid of layout for this design element
+
+- plink
+
+ permalink for this item if different than the default
+
+- verb
+
+ activitystream verb for this item/activity
+
+- obj_type
+
+ activitystream object type for this item/activity
+
+
+
+Example:
+
+ curl -u mychannel:mypassword https://xyz.macgirvin.com/api/z/1.0/item/update -d body="hello world"
+
+
+Returns:
+
+[code nowrap]
+ {
+
+ "success": true,
+ "item_id": "2245",
+ "item": {
+ "id": "2245",
+ "mid": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "aid": "1",
+ "uid": "2",
+ "parent": "2245",
+ "parent_mid": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "thr_parent": "14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "created": "2016-12-03 20:00:12",
+ "edited": "2016-12-03 20:00:12",
+ "expires": "0001-01-01 00:00:00",
+ "commented": "2016-12-03 20:00:12",
+ "received": "2016-12-03 20:00:12",
+ "changed": "2016-12-03 20:00:12",
+ "comments_closed": "0001-01-01 00:00:00",
+ "owner_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "author_xchan": "pgcJx1IQjuPkx8aI9qheJlBMZzJz-oTPjHy3h5pWlOVOriBO_cSiUhhqwhuZ74TYJ8_ECO3pPiRMWC0q8YPCQg",
+ "source_xchan": "",
+ "mimetype": "text/bbcode",
+ "title": "",
+ "body": "hello world",
+ "html": "",
+ "app": "",
+ "lang": "",
+ "revision": "0",
+ "verb": "http://activitystrea.ms/schema/1.0/post",
+ "obj_type": "http://activitystrea.ms/schema/1.0/note",
+ "obj": "",
+ "tgt_type": "",
+ "target": "",
+ "layout_mid": "",
+ "postopts": "",
+ "route": "",
+ "llink": "https://xyz.macgirvin.com/display/14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "plink": "https://xyz.macgirvin.com/channel/mychannel/?f=&mid=14135cdecf6b8e3891224e4391748722114da6668eebbcb56fe4667b60b88249@xyz.macgirvin.com",
+ "resource_id": "",
+ "resource_type": "",
+ "attach": "",
+ "sig": "sa4TOQNfHtV13HDZ1tuQGWNBpZp-nWhT2GMrZEmelXxa_IvEepD2SEsCTWOBqM8OKPJLfNy8_i-ORXjrOIIgAa_aT8cw5vka7Q0C8L9eEb_LegwQ_BtH0CXO5uT30e_8uowkwzh6kmlVg1ntD8QqrGgD5jTET_fMQOIw4gQUBh40GDG9RB4QnPp_MKsgemGrADnRk2vHO7-bR32yQ0JI-8G-eyeqGaaJmIwkHoi0vXsfjZtU7ijSLuKEBWboNjKEDU89-vQ1c5Kh1r0pmjiDk-a5JzZTYShpuhVA-vQgEcADA7wkf4lJZCYNwu3FRwHTvhSMdF0nmyv3aPFglQDky38-SAXZyQSvd7qlABHGCVVDmYrYaiq7Dh4rRENbAUf-UJFHPCVB7NRg34R8HIqmOKq1Su99bIWaoI2zuAQEVma9wLqMoFsluFhxX58KeVtlCZlro7tZ6z619-dthS_fwt0cL_2dZ3QwjG1P36Q4Y4KrCTpntn9ot5osh-HjVQ01h1I9yNCj6XPgYJ8Im3KT_G4hmMDFM7H9RUrYLl2o9XYyiS2nRrf4aJHa0UweBlAY4zcQG34bw2AMGCY53mwsSArf4Hs3rKu5GrGphuwYX0lHa7XEKMglwBWPWHI49q7-oNWr7aWwn1FnfaMfl4cQppCMtKESMNRKm_nb9Dsh5e0",
+ "diaspora_meta": "",
+ "location": "",
+ "coord": "",
+ "public_policy": "",
+ "comment_policy": "contacts",
+ "allow_cid": "",
+ "allow_gid": "",
+ "deny_cid": "",
+ "deny_gid": "",
+ "item_restrict": "0",
+ "item_flags": "0",
+ "item_private": "0",
+ "item_origin": "1",
+ "item_unseen": "0",
+ "item_starred": "0",
+ "item_uplink": "0",
+ "item_consensus": "0",
+ "item_wall": "1",
+ "item_thread_top": "1",
+ "item_notshown": "0",
+ "item_nsfw": "0",
+ "item_relay": "0",
+ "item_mentionsme": "0",
+ "item_nocomment": "0",
+ "item_obscured": "0",
+ "item_verified": "1",
+ "item_retained": "0",
+ "item_rss": "0",
+ "item_deleted": "0",
+ "item_type": "0",
+ "item_hidden": "0",
+ "item_unpublished": "0",
+ "item_delayed": "0",
+ "item_pending_remove": "0",
+ "item_blocked": "0"
+ }
+
+ }
+[/code]
+[h3]item/full[/h3]
+
+
+Get all data associated with an item
+
+[h3]abook[/h3]
+
+
+Connections
+
+[h3]abconfig[/h3]
+
+
+Connection metadata (such as permissions)
+
+[h3]perm_allowed[/h3]
+
+
+Check a permission for a given xchan
diff --git a/doc/developer/zot_protocol.bb b/doc/developer/zot_protocol.bb
new file mode 100644
index 000000000..b87e1cd73
--- /dev/null
+++ b/doc/developer/zot_protocol.bb
@@ -0,0 +1,479 @@
+[h3] What is Zot?[/h3]
+Zot is the revolutionary protocol that powers $Projectname, providing [b]communications[/b], [b]identity management[/b], and [b]access control[/b] across a fully [b]decentralised[/b] network of independent websites, often called "the grid". The resulting platform is a robust system that supports privacy and security while enabling the kind of rich web services typically seen only in centralized, proprietary solutions.
+
+Consider this typical scenario:
+
+Jaquelina wishes to share photos with Roberto from her blog at [b]jaquelina.org[/b], but to nobody else. Roberto maintains his own family hub at [b]roberto.net[/b] on a completely independent server. Zot allows Jaquelina to publish her photos using an [i]access control list (ACL)[/i] that includes only Roberto. That means that while Roberto can see the photos when he visits her blog, his brother Marco cannot, and neither can any of his other family members who have accounts on [b]roberto.net[/b].
+
+The magic in this scenario comes from the fact that Roberto never logged in to Jaquelina's website. Instead, he had to login only once using his password on his [i]own[/i] website at [b]roberto.net[/b]. When Roberto visits [b]jaquelina.org[/b], her hub seamlessly authenticates him by remotely querying his server in the background.
+
+It is not uncommon for servers to have technical problems or become inaccessible for a variety of reasons. Zot provides robustness for Roberto's online activities by allowing him to have [i]clones[/i] of his online identity, or [i]channel[/i], on multiple independent hubs. Imagine that Roberto's server crashes for some reason and he cannot log in there. He simply logs in to one of his clones at [b]gadfly.com[/b], a site operated by his friend Peter. Once authenticated at [b]gadfly.com[/b], Roberto can view Jaquelina's blog as before, without Jaquelina having to grant any additional access!
+
+[h4] Communications[/h4]
+Communications and social networking are an integral part of the grid. Any channel (and any services provided by that channel) can make full use of feature-rich social communications on a global scale. These communications may be public or private - and private communications comprise not only fully encrypted transport, but also encrypted storage to help protect against accidental snooping and disclosure by rogue system administrators and internet service providers.
+
+Zot supports a wide array of background services in the grid, from friend suggestions to directory services. New content and data updates are propagated in the background between hubs across the grid according to access control lists and permissions specified by both sender [i]and[/i] receiver channels. Data is also synchronized between an arbitrary number of channel clones, allowing hub members to access data and continue collaborating seamlessly in the event that their primary hub is inaccessible or offline.
+
+[h4] Identity [/h4]
+Zot's identity layer is unique. It provides [b]invisible single sign-on[/b] across all sites in the grid.
+
+It also provides [b]nomadic identity[/b], so that your communications with friends, family, and or anyone else you're communicating with won't be affected by the loss of your primary communication node - either temporarily or permanently.
+
+The important bits of your identity and relationships can be backed up to a thumb drive, or your laptop, and may appear at any node in the grid at any time - with all your friends and preferences intact.
+
+Crucially, these nomadic instances are kept in sync so any instance can take over if another one is compromised or damaged. This protects you against not only major system failure, but also temporary site overloads and governmental manipulation or censorship.
+
+Nomadic identity, single sign-on, and $Projectname's decentralisation of hubs, we believe, introduce a high degree of degree of [b]resiliency[/b] and [b]persistence[/b] in internet communications, that are sorely needed amidst global trends towards corporate centralization, as well as mass and indiscriminate government surveillance and censorship.
+
+As you browse the grid, viewing channels and their unique content, you are seamlessly authenticated as you go, even across completely different server hubs. No passwords to enter. Nothing to type. You're just greeted by name on every new site you visit.
+
+How does Zot do that? We call it [b]magic-auth[/b], because $Projectname hides the details of the complexities that go into single sign-on logins, and nomadic identities, from the experience of browsing on the grid. This is one of the design goals of $Projectname: to increase privacy, and freedom on the web, while reducing the complexity and tedium brought by the need to enter new passwords and login names for every different sight that someone might visit online. You login only once on your home hub (or any nomadic backup hub you have chosen). This allows you to access any authenticated services provided anywhere in the grid - such as shopping, blogs, forums, and access to private information. Your password isn't stored on a thousand different sites; it is stored on servers that you control or that you have chosen to trust.
+
+You cannot be silenced. You cannot be removed from the grid unless you yourself choose to exit it.
+
+[h4] Access Control[/h4]
+Zot's identity layer allows you to provide fine-grained permissions to any content you wish to publish - and these permissions extend across the grid. This is like having one super huge website made up of an army of small individual websites - and where each channel in the grid can completely control their privacy and sharing preferences for any web resources they create.
+
+Currently, $Projectname supports access control for many types of data, including post/comment discussion threads, photo albums, events, cloud files, web pages, wikis, and more. Every object and how it is shared and with whom is completely under your control.
+
+This type of control is trivial on large corporate providers because they own the user database. Within the grid, there is no need for a huge user database on your machine - because the grid [b]is[/b] your user database. It has what is essentially infinite capacity (limited by the total number of hubs online across the internet), and is spread amongst hundreds, and potentially millions of computers.
+
+Access can be granted or denied for any resource, to any channel, or any group of channels; anywhere within the grid. Others can access your content if you permit them to do so, and they do not even need to have an account on your hub.
+
+[h3]Technical Introduction[/h3]
+Zot is a JSON-based web framework for implementing secure decentralised communications and services. In order to provide this functionality, Zot creates a decentralised globally unique identifier for each hub on the network. This global identifier is not linked inextricably to DNS, providing the requisite mobility. Many existing decentralised communications frameworks provide the communication aspect, but do not provide remote access control and authentication. Additionally most of these are based on 'webfinger', which still binds identity to domain names and cannot support nomadic identity.
+
+The primary issues Zot addresses are
+
+[list]
+[*] completely decentralised communications
+[*] independence from DNS-based identity
+[*] node mobility
+[*] seamless remote authentication
+[*] high performance
+[/list]
+We will rely on DNS-based user@host addresses as a "user-friendly" mechanism to let people know where you are, specifically on a named host with a given username, and communication will be carried out to DNS entities using TCP and the web.
+
+But the underlying protocol will provide an abstraction layer on top of this, so that a communications node (e.g. "identity") can move to an alternate DNS location and (to the best of our ability) gracefully recover from site re-locations and/or maintain pre-existing communication relationships. A side effect of this requirement is the ability to communicate from alternate/multiple DNS locations and service providers and yet maintain a single online identity.
+
+We will call this overlay network the "grid". Servers attached to this network are known as "hubs" and may support any number of individual identities.
+
+An identity does not necessarily correspond to a person. It is just something which requires the ability to communicate within the grid.
+
+The ability to recover will be accomplished by communication to the original location when creating a new or replacement identity, or as a fallback from a stored file describing the identity and their contacts in the case where the old location no longer responds.
+
+At least on the short term, the mobility of existing content is not a top priority. This may or may not take place at a later stage. The most important things we want to keep are your identity and your friends.
+
+Addresses which are shared amongst people are user@host, and which describe the [b]current[/b] local account credentials for a given identity. These are DNS based addresses and used as a seed to locate a given identity within the grid. The machine communications will bind this address to a globally unique ID. A single globally unique ID may be attached or bound to any number of DNS locations. Once an identity has been mapped or bound to a DNS location, communications will consist of just knowing the globally unique address, and what DNS (url) is being used currently (in order to call back and verify/complete the current communication). These concepts will be specified in better detail.
+
+In order for an identity to persist across locations, one must be able to provide or recover
+
+[list]
+[*] the globally unique ID for that identity
+[*] the private key assigned to that identity
+[*] (if the original server no longer exists) an address book of contacts for that identity.
+[/list]
+This information will be exportable from the original server via API, and/or downloadable to disk or thumb-drive.
+
+We may also attempt to recover with even less information, but doing so is prone to account hijacking and will require that your contacts confirm the change.
+
+In order to implement high performance communications, the data transfer format for all aspects of Zot is JSON. XML communications require way too much overhead.
+
+Bi-directional encryption is based on RSA 4096-bit keys expressed in DER/ASN.1 format using the PKCS#8 encoding variant, with AES-256-CBC used for block encryption of variable length or large items.
+
+Some aspects of well known "federation protocols" (webfinger, salmon, activitystreams, portablecontacts, etc.) may be used in zot, but we are not tied to them and will not be bound by them. $Projectname project is attempting some rather novel developments in decentralised communications and if there is any need to diverge from such "standard protocols" we will do so without question or hesitation.
+
+In order to create a globally unique ID, we will base it on a whirlpool hash of the identity URL of the origination node and a psuedo-random number, which should provide us with a 256 bit ID with an extremely low probability of collision (256 bits represents approximately 115 quattuorviginitillion or 1.16 X 10^77 unique numbers). This will be represented in communications as a base64url-encoded string. We will not depend on probabilities however and the ID must also be attached to a public key with public key cryptography used to provide an assurance of identity which has not been copied or somehow collided in whirlpool hash space.
+
+Basing this ID on DNS provides a globally unique seed, which would not be the case if it was based completely on psuedo-random number generation.
+
+We will refer to the encoded globally unique uid string as zot_uid
+
+As there may be more than one DNS location attached/bound to a given zot_uid identity, delivery processes should deliver to all of them - as we do not know for sure which hub instance may be accessed at any given time. However we will designate one DNS location as "primary" and which will be the preferred location to view web profile information.
+
+We must also provide the ability to change the primary to a new location. A look-up of information on the current primary location may provide a "forwarding pointer" which will tell us to update our records and move everything to the new location. There is also the possibility that the primary location is defunct and no longer responding. In that case, a location which has already been mapped to this zot_uid can seize control, and declare itself to be primary. In both cases the primary designation is automatically approved and moved. A request can also be made from a primary location which requests that another location be removed.
+
+In order to map a zot_uid to a second (or tertiary) location, we require a secure exchange which verifies that the new location is in possession of the private key for this zot_uid. Security of the private key is thus essential to avoid hijacking of identities.
+
+Communications will then require
+[list]
+[*] zot_uid (string)
+[*] uid_sig
+[*] callback (current location Zot endpoint url)
+[*] callback_sig
+[*] spec (int)
+[/list]
+passed with every communique. The spec is a revision number of the applicable Zot spec so that communications can be maintained with hubs using older and perhaps incompatible protocol specifications. Communications are verified using a stored public key which was copied when the connection to this zot_uid was first established.
+
+Key revocation and replacement must take place from the primary hub. The exact form for this is still being worked out, but will likely be a notification to all other bound hubs to "phone home" (to the primary hub) and request a copy of the new key. This communique should be verified using a site or hub key; as the original identity key may have been compromised and cannot be trusted.
+
+In order to eliminate confusion, there should be exactly one canonical url for any hub, so that these can be indexed and referenced without ambiguity.
+
+So as to avoid ambiguity of scheme, it is strongly encouraged that all addresses to be https with a "browser valid" cert and a single valid host component (either www.domain.ext or domain.ext, but not both), which is used in all communications. Multiple URLs may be provided locally, but only one unique URL should be used for all Zot communications within the grid.
+
+Test installation which do not connect to the public grid may use non-SSL, but all traffic flowing over public networks should be safe from session-hijacking, preferably with a "browser recognised" cert.
+
+Where possible, Zot encourages the use of "batching" to minimise network traffic between two hubs. This means that site 'A' can send multiple messages to site 'B' in a single transaction, and also consolidate deliveries of identical messages to multiple recipients on the same hub.
+
+Messages themselves may or may not be encrypted in transit, depending on the private nature of the messages. SSL (strongly encouraged) provides unconditional encryption of the data stream, however there is little point in encrypting public communications which have been designated as having unrestricted visibility. The encryption of data storage and so-called "end-to-end encryption" is outside the scope of zot. It is presumed that hub operators will take adequate safeguards to ensure the security of their data stores and these are functions of application and site integrity as opposed to protocol integrity.
+
+
+[h4]Messages[/h4]
+
+Given the constraints listed previously, a Zot communique should therefore be a json array of individual messages. These can be mixed and combined within the same transmission.
+
+Each message then requires:
+[list]
+[*] type
+[*] (optional) recipient list
+[/list]
+Lack of a recipient list would indicate an unencrypted public or site level message. The recipient list would contain an array of zot_uid with an individual decryption key, and a common iv. The decryption key is encoded with the recipient identity's public key. The iv is encrypted with the sender's private key.
+
+All messages should be digitally signed by the sender.
+
+The type can be one of (this list is extensible):
+[list]
+[*] post (or activity)
+[*] mail
+[*] identity
+[*] authenticate
+[/list]
+Identity messages have no recipients and notify the system social graph of an identity update, which could be a new or deleted identity, a new or deleted location, or a change in primary hub. The signature for these messages uses system keys as opposed to identity-specific keys.
+
+Posts include many different types of activities, such as top-level posts, likes/dislikes, comments, tagging activities, etc. These types are indicated within the message sturcture.
+
+authenticate messages result in mutual authentication and browser redirect to protected resources on the remote hub such as the ability to post wall-to-wall messages and view private photo albums and events, etc.
+
+[h4]Discovery[/h4]
+
+A well-known url is used to probe a hub for Zot capabilities and identity lookups, including the discovery of public keys, profile locations, profile photos, and primary hub location.
+
+The location for this service is /.well-known/zot-info - and must be available at the root of the chosen domain.
+
+To perform a lookup, a POST request is made to the discovery location with the following parameters:
+
+Required:
+
+address => an address on the target system such as "john"
+
+Optional
+
+target => the Zot "guid" of the observer for evaluating permissions
+
+target_sig => an RSA signature (base64url encoded) of the guid
+
+key => The public key needed to verify the signature
+
+token => a string (possibly random) chosen by the requesting service. If provided, an entry in the discovered packet will be provided called 'signed_token' which consists of the base64url_encoded RSA signature of the concatenation of the string 'token.' and the provided token using the private key of the discovered channel. This can be verified using the provided 'key' entry, and provides assurance that the server is in possession of the private key for the discovered identity. After 2017-01-01 it is [b]required[/b] that a server provide a signed_token [i]if[/i] a token was provided in the request.
+
+With no target provided, the permissions returned will be generic permissions
+for unknown or unauthenticated observers
+
+Example of discovery packet for 'mike@zothub.com'
+[code nowrap]
+ {
+
+ "success": true,
+ "signed_token": "KBJrKTq1qrctNuxF3GwVh3GAGRqmgkirlXANPcJZAeWlvSt_9TMV097slR4AYnYCBEushbVqHEJ9Rb5wHTa0HzMbfRo8cRdl2yAirvvv5d98dtwHddQgX1jB0xEypXtmIYMdPGDLvhI1RNdIBhHkkrRcNreRzoy4xD--HM6m1W0-A8PJJJ9BcNxmGPcBtLzW08wzoP9trJ3M7DQ6Gkk6j7iwVsyApw1ZBaDvabGTdc_SFV-Iegtqw3rjzT_xXWsfzMlKBy-019MYn_KS-gu23YzjvGu5tS_zDfkQb8DMUlPLz5yyxM0yOMlUDtG2qQgIJAU2O0X6T5xDdJ6mtolNyhepg845PvFDEqBQGMIH1nc47CNumeudDi8IWymEALhjG_U8KAK7JVlQTJj2EKUb0au1g6fpiBFab5mmxCMtZEX3Jreyak5GOcFFz-WpxuXJD9TdSoIvaBfBFOoJnXkg2zE4RHXeQzZ2FotmrbBG5dm8B-_6byYGoHBc08ZsWze1K96JIeRnLpBaj6ifUDcVHxZMPcGHHT27dvU2PNbgLiBjlAsxhYqkhN5qOHN8XBcg2KRjcMBaI3V0YMxlzXz5MztmZq3fcB1p-ccIoIyMPMzSj3yMB7J9CEU2LYPSTHMdPkIeDE6GaCkQKviaQQJQde346tK_YjA2k7_SOBmvPYE",
+ "guid": "sebQ-IC4rmFn9d9iu17m4BXO-kHuNutWo2ySjeV2SIW1LzksUkss12xVo3m3fykYxN5HMcc7gUZVYv26asx-Pg",
+ "guid_sig": "Llenlbl4zHo6-g4sa63MlQmTP5dRCrsPmXHHFmoCHG63BLq5CUZJRLS1vRrrr_MNxr7zob_Ykt_m5xPKe5H0_i4pDj-UdP8dPZqH2fqhhx00kuYL4YUMJ8gRr5eO17vsZQ3XxTcyKewtgeW0j7ytwMp6-hFVUx_Cq08MrXas429ZrjzaEwgTfxGnbgeQYQ0R5EXpHpEmoERnZx77VaEahftmdjAUx9R4YKAp13pGYadJOX5xnLfqofHQD8DyRHWeMJ4G1OfWPSOlXfRayrV_jhnFlZjMU7vOdQwHoCMoR5TFsRsHuzd-qepbvo3pzvQZRWnTNu6oPucgbf94p13QbalYRpBXKOxdTXJrGdESNhGvhtaZnpT9c1QVqC46jdfP0LOX2xrVdbvvG2JMWFv7XJUVjLSk_yjzY6or2VD4V6ztYcjpCi9d_WoNHruoxro_br1YO3KatySxJs-LQ7SOkQI60FpysfbphNyvYMkotwUFI59G08IGKTMu3-GPnV1wp7NOQD1yzJbGGEGSEEysmEP0SO9vnN45kp3MiqbffBGc1r4_YM4e7DPmqOGM94qksOcLOJk1HNESw2dQYWxWQTBXPfOJT6jW9_crGLMEOsZ3Jcss0XS9KzBUA2p_9osvvhUKuKXbNztqH0oZIWlg37FEVsDs_hUwUJpv2Ar09k4",
+ "key": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7QCwvuEIwCHjhjbpz3Oc\ntyei/Pz9nDksNbsc44Cm8jxYGMXsTPFXDZYCcCB5rcAhPPdZSlzaPkv4vPVcMIrw\n5cdX0tvbwa3rNTng6uFE7qkt15D3YCTkwF0Y9FVZiZ2Ko+G23QeBt9wqb9dlDN1d\nuPmu9BLYXIT/JXoBwf0vjIPFM9WBi5W/EHGaiuqw7lt0qI7zDGw77yO5yehKE4cu\n7dt3SakrXphL70LGiZh2XGoLg9Gmpz98t+gvPAUEotAJxIUqnoiTA8jlxoiQjeRK\nHlJkwMOGmRNPS33awPos0kcSxAywuBbh2X3aSqUMjcbE4cGJ++/13zoa6RUZRObC\nZnaLYJxqYBh13/N8SfH7d005hecDxWnoYXeYuuMeT3a2hV0J84ztkJX5OoxIwk7S\nWmvBq4+m66usn6LNL+p5IAcs93KbvOxxrjtQrzohBXc6+elfLVSQ1Rr9g5xbgpub\npSc+hvzbB6p0tleDRzwAy9X16NI4DYiTj4nkmVjigNo9v2VPnAle5zSam86eiYLO\nt2u9YRqysMLPKevNdj3CIvst+BaGGQONlQalRdIcq8Lin+BhuX+1TBgqyav4XD9K\nd+JHMb1aBk/rFLI9/f2S3BJ1XqpbjXz7AbYlaCwKiJ836+HS8PmLKxwVOnpLMbfH\nPYM8k83Lip4bEKIyAuf02qkCAwEAAQ==\n-----END PUBLIC KEY-----\n",
+ "name": "Mike Macgirvin",
+ "name_updated": "2012-12-06 04:59:13",
+ "address": "mike@zothub.com",
+ "photo_mimetype": "image/jpeg",
+ "photo": "https://zothub.com/photo/profile/l/1",
+ "photo_updated": "2012-12-06 05:06:11",
+ "url": "https://zothub.com/channel/mike",
+ "connections_url": "https://zothub.com/poco/mike",
+ "target": "",
+ "target_sig": "",
+ "searchable": false,
+ "permissions": {
+ "view_stream": true,
+ "view_profile": true,
+ "view_photos": true,
+ "view_contacts": true,
+ "view_storage": true,
+ "view_pages": true,
+ "send_stream": false,
+ "post_wall": false,
+ "post_comments": false,
+ "post_mail": false,
+ "post_photos": false,
+ "tag_deliver": false,
+ "chat": false,
+ "write_storage": false,
+ "write_pages": false,
+ "delegate": false
+ },
+ "profile": {
+ "description": "Freedom Fighter",
+ "birthday": "0000-05-14",
+ "next_birthday": "2013-05-14 00:00:00",
+ "gender": "Male",
+ "marital": "It's complicated",
+ "sexual": "Females",
+ "locale": "",
+ "region": "",
+ "postcode": "",
+ "country": "Australia"
+ },
+ "locations": [
+ {
+ "host": "zothub.com",
+ "address": "mike@zothub.com",
+ "primary": true,
+ "url": "https://zothub.com",
+ "url_sig": "eqkB_9Z8nduBYyyhaSQPPDN1AhSm5I4R0yfcFxPeFpuu17SYk7jKD7QzvmsyahM5Kq7vDW6VE8nx8kdFYpcNaurqw0_IKI2SWg15pGrhkZfrCnM-g6A6qbCv_gKCYqXvwpSMO8SMIO2mjQItbBrramSbWClUd2yO0ZAceq3Z_zhirCK1gNm6mGRJaDOCuuTQNb6D66TF80G8kGLklv0o8gBfxQTE12Gd0ThpUb5g6_1L3eDHcsArW_RWM2XnNPi_atGNyl9bS_eLI2TYq0fuxkEdcjjYx9Ka0-Ws-lXMGpTnynQNCaSFqy-Fe1aYF7X1JJVJIO01LX6cCs-kfSoz29ywnntj1I8ueYldLB6bUtu4t7eeo__4t2CUWd2PCZkY3PKcoOrrnm3TJP5_yVFV_VpjkcBCRj3skjoCwISPcGYrXDufJxfp6bayGKwgaCO6QoLPtqqjPGLFm-fbn8sVv3fYUDGilaR3sFNxdo9mQ3utxM291XE2Pd0jGgeUtpxZSRzBuhYeOybu9DPusID320QbgNcbEbEImO8DuGIxuVRartzEXQF4WSYRdraZzbOqCzmU0O55P836JAfrWjgxTQkXlYCic-DBk-iE75JeT72smCtZ4AOtoFWCjZAABCw42J7JELY9APixZXWriKtjy6JI0G9d3fs6r7SrXr1JMy0",
+ "callback": "https://zothub.com/post",
+ "sitekey": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1IWXwd/BZuevq8jzNFoR\n3VkenduQH2RpR3Wy9n4+ZDpbrUKGJddUGm/zUeWEdKMVkgyllVA/xHdB7jdyKs1X\nuIet9mIdnzvhdLO/JFD5hgbNG2wpSBIUY6aSNeCFTzszqXmuSXMW5U0Ef5pCbzEA\nnhoCoGL1KAgPqyxnGKUlj7q2aDwC9IRNtAqNyFQL67oT91vOQxuMThjlDhbR/29Q\ncYR4i1RzyahgEPCnHCPkT2GbRrkAPjNZAdlnk9UesgP16o8QB3tE2j50TVrbVc/d\nYRbzC56QMPP9UgUsapNeSJBHji75Ip/E5Eg/kfJC/HEQgyCqjCGfb7XeUaeQ7lLO\nqc7CGuMP+Jqr/cE54/aSHg8boTwxkMp11Ykb+ng17fl57MHTM2RJ99qZ1KBkXezR\nuH1lyvjzeJPxEFr9rkUqc4GH74/AgfbgaFvQc8TS7ovEa5I/7Pg04m7vLSEYc6UF\nYJYxXKrzmZT2TDoKeJzaBBx5MFLhW19l68h9dQ8hJXIpTP0hJrpI+Sr6VUAEfFQC\ndIDRiFcgjz6j7T/x8anqh63/hpsyf2PMYph1+4/fxtSCWJdvf+9jCRM8F1IDfluX\n87gm+88KBNaklYpchmGIohbjivJyru41CsSLe0uinQFvA741W00w6JrcrOAX+hkS\nRQuK1dDVwGKoIY85KtTUiMcCAwEAAQ==\n-----END PUBLIC KEY-----\n"
+ }
+ ],
+ "site": {
+ "url": "https://zothub.com",
+ "directory_mode": "primary",
+ "directory_url": "https://zothub.com/dirsearch"
+ }
+
+ }
+[/code]
+
+
+Discovery returns a JSON array with the following components:
+
+'success' => ('1' or '') Operation was successful if '1'. Otherwise an optional 'message' may be present indicating the source of error.
+
+'signed_token' => If a token parameter was provided in the request, it is prepended with the text 'token.' and then RSA signed with the channel private key and base64url encoded and returned as 'signed_token'.
+
+'guid' => the guid of the address on the target system
+
+'guid_sig' => the base64url encoded RSA signature of the guid, signed with the private key associated with that guid.
+
+'key' => the public key associated with that guid
+
+'name' => channel name
+
+'name_updated' => MySQL style timestamp '2012-01-01 00:00:00' when the name was last changed (UTC)
+
+'address' => "webbie" or user@host address associated with this channel
+
+'photo' => URL of a profile photo for this channel (ideally 175x175)
+
+'photo_mimetype' => content-type of the profile photo
+
+'photo_updated' => MySQL style timestamp when photo was last updated (UTC)
+
+'url' => location of channel homepage
+
+'connections_url' => location of Portable Contacts (extended for zot) URL for this channel
+
+'target' => if a permissions target was specified, it is mirrored
+
+'target_sig' => if a permissions target was specified, the signature is mirrored.
+
+'searchable' => ('1' or '') '1' indicates this entry can be searched in a directory
+
+[h5]Permissions[/h5]
+
+
+'permisssions' => extensible array of permissions appropriate to this target, values are '1' or ''
+
+ Permissions may include:
+[list]
+[*] view_stream
+[*] view_profile
+[*] view_photos
+[*] view_contacts
+[*] view_storage
+[*] view_pages
+[*] send_stream
+[*] post_wall
+[*] post_comments
+[*] post_mail
+[*] post_photos
+[*] tag_deliver
+[*] chat
+[*] write_storage
+[*] write_pages
+[*] delegate
+[/list]
+
+
+[h5]Profile[/h5]
+
+
+'profile' => array of important profile fields
+[list]
+[*] description
+[*] birthday YYYY-MM-DD , all fields are optional, any field (such as year) may be zero
+[*] next_birthday => MySQL datetime string representing the next upcoming birthday, converted from the channel's default timezone to UTC.
+[*] gender (free form)
+[*] marital (marital status)
+[*] sexual (preference)
+[*] locale (city)
+[*] region (state)
+[*] postcode
+[*] country
+[/list]
+
+[h5]Locations[/h5]
+
+
+'locations' => array of registered locations (DNS locations) this channel may be visible or may be posting from
+
+Each location is an array of
+
+'host' => DNS hostname, e.g. example.com
+
+'address' => the webbie or user@host identifier associated with this location
+
+'primary' => ('1' or '') whether or not this is the primary location for this channel where files and web pages are generally found
+
+'url' => url of the root of this DNS location e.g. https://example.com
+
+'url_sig' => base64url encoded RSA signature of the URL, signed with the channel private key
+
+'callback' => Zot communications endpoint on this site, usually https://example.com/post
+
+'sitekey' => public key of this site/host
+
+
+[h5]Site[/h5]
+
+
+'site' => array providing the directory role of the site responding to this request
+
+'url' => url of this site e.g. https://example.com
+
+'directory_mode' => one of 'primary', 'secondary', 'normal', or 'standalone'
+
+'directory_url' => if this is a directory server or standalone, the URL for the directory search module
+
+
+
+[h3]Magic Auth[/h3]
+
+So-called "magic auth" takes place by a special exchange. On the remote computer, a redirection is made to the Zot endpoint with special GET parameters.
+
+Endpoint: https://example.com/post/name
+
+where 'name' is the left hand side of the channel webbie, for instance 'mike' where the webbie is 'mike@zothub.com'
+
+Additionally four parameters are supplied:
+[list]
+[*] auth => the webbie of the person requesting access
+[*] dest => the desired destination URL (urlencoded)
+[*] sec => a random string which is also stored locally for use during the verification phase.
+[*] version => the Zot revision
+[/list]
+When this packet is received, a Zot message is initiated to the auth identity:
+
+[code nowrap]
+ {
+ "type":"auth_check",
+ "sender":{
+ "guid":"kgVFf_1_SSbyqH-BNWjWuhAvJ2EhQBTUdw-Q1LwwssAntr8KTBgBSzNVzUm9_RwuDpxI6X8me_QQhZMf7RfjdA",
+ "guid_sig":"PT9-TApzpm7QtMxC63MjtdK2nUyxNI0tUoWlOYTFGke3kNdtxSzSvDV4uzq_7SSBtlrNnVMAFx2_1FDgyKawmqVtRPmT7QSXrKOL2oPzL8Hu_nnVVTs_0YOLQJJ0GYACOOK-R5874WuXLEept5-KYg0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD-yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q",
+ "url":"http:\/\/podunk.edu",
+ "url_sig":"T8Bp7j5DHHhQDCFcAHXfuhUfGk2P3inPbImwaXXF1xJd3TGgluoXyyKDx6WDm07x0hqbupoAoZB1qBP3_WfvWiJVAK4N1FD77EOYttUEHZ7L43xy5PCpojJQmkppGbPJc2jnTIc_F1vvGvw5fv8gBWZvPqTdb6LWF6FLrzwesZpi7j2rsioZ3wyUkqb5TDZaNNeWQrIEYXrEnWkRI_qTSOzx0dRTsGO6SpU1fPWuOOYMZG8Nh18nay0kLpxReuHCiCdxjXRVvk5k9rkcMbDBJcBovhiSioPKv_yJxcZVBATw3z3TTE95kGi4wxCEenxwhSpvouwa5b0hT7NS4Ay70QaxoKiLb3ZjhZaUUn4igCyZM0h6fllR5I6J_sAQxiMYD0v5ouIlb0u8YVMni93j3zlqMWdDUZ4WgTI7NNbo8ug9NQDHd92TPmSE1TytPTgya3tsFMzwyq0LZ0b-g-zSXWIES__jKQ7vAtIs9EwlPxqJXEDDniZ2AJ6biXRYgE2Kd6W_nmI7w31igwQTms3ecXe5ENI3ckEPUAq__llNnND7mxp5ZrdXzd5HHU9slXwDShYcW3yDeQLEwAVomTGSFpBrCX8W77n9hF3JClkWaeS4QcZ3xUtsSS81yLrp__ifFfQqx9_Be89WVyIOoF4oydr08EkZ8zwlAsbZLG7eLXY"
+ },
+ "recipients":{
+ {
+ "guid":"ZHSqb3yGar3TYV_o9S-JkD-6o_V4DhUcxtv0VeyX8Kj_ENHPI_M3SyAUucU835-mIayGMmTpqJz3ujPkcavVhA",
+ "guid_sig":"JsAAXigNghTkkbq8beGMJjj9LBKZn28hZ-pHSsoQuwYWvBJ2lSnfc4r9l--WgO6sucH-SR6RiBo78eWn1cZrh_cRMu3x3LLx4y-tjixg-oOOgtZakkBg4vmOhkKPkci0mFtzvUrpY4YHySqsWTuPwRx_vOlIYIGEY5bRXpnkNCoC8J4EJnRucDrgSARJvA8QQeQQL0H4mWEdGL7wlsZp_2VTC6nEMQ48Piu6Czu5ThvLggGPDbr7PEMUD2cZ0jE4SeaC040REYASq8IdXIEDMm6btSlGPuskNh3cD0AGzH2dMciFtWSjmMVuxBU59U1I6gHwcxYEV6BubWt_jQSfmA3EBiPhKLyu02cBMMiOvYIdJ3xmpGoMY1Cn__vhHnx_vEofFOIErb6nRzbD-pY49C28AOdBA5ffzLW3ss99d0A-6GxZmjsyYhgJu4tFUAa7JUl84tMbq28Tib0HW6qYo6QWw8K1HffxcTpHtwSL5Ifx0PAoGMJsGDZDD1y_r9a4vH5pjqmGrjL3RXJJUy-m4eLV5r7xMWXsxjqu3D8r04_dcw4hwwexpMT1Nwf8CTB0TKb8ElgeOpDFjYVgrqMYWP0XdhatcFtAJI7gsS-JtzsIwON9Kij66-VAkqy_z1IXI0ziyqV1yapSVYoUV1vMScRZ_nMqwiB5rEDx-XLfzko"
+ }
+ }
+ "callback":"\/post",
+ "version":1,
+ "secret":"1eaa6613699be6ebb2adcefa5379c61a3678aa0df89025470fac871431b70467",
+ "secret_sig":"eKV968b1sDkOVdSMi0tLRtOhQw4otA8yFKaVg6cA4I46_zlAQGbFptS-ODiZlSAqR7RiiZQv4E2uXCKar52dHo0vvNKbpOp_ezWYcwKRu1shvAlYytsflH5acnDWL-FKOOgz5zqLLZ6cKXFMoR1VJGG_Od-DKjSwajyV9uVzTry58Hz_w0W2pjxwQ-Xv11rab5R2O4kKSW77YzPG2R5E6Q7HN38FrLtyWD_ai3K9wlsFOpwdYC064dk66X7BZtcIbKtM6zKwMywcfJzvS5_0U5yc5GGbIY_lY6SViSfx9shOKyxkEKHfS29Ynk9ATYGnwO-jnlMqkJC7t149H-sI9hYWMkLuCzaeLP56k2B2TmtnYvE_vHNQjzVhTwuHCIRVr-p6nplQn_P3SkOpYqPi3k_tnnOLa2d3Wtga8ClEY90oLWFJC3j2UkBf_VEOBNcg-t5XO3T-j9O4Sbk96k1Qoalc-QlznbGx4bOVsGkRBBMiH4YUqiiWB_OkFHtdqv7dqGeC-u-B4u9IxzYst46vvmyA3O-Q4APSZ1RY8ITUH0jLTbh6EAV7Oki8pIbOg0t56p-8RlanOZqmFvR-grVSc7Ak1ZcD8NACmvidUpa1B7WEvRcOeffx9lype0bt5XenDnMyx6szevwxZIiM8qGM2lsSk4fu8HI9cW0mLywzZT0"
+ }
+[/code]
+
+auth_check messages MUST be encrypted with AES256CBC. This message is sent to the origination site, which checks the 'secret' to see if it is the same as the 'sec' which it passed originally. It also checks the secret_sig which is the secret signed by the destination channel's private key and base64url encoded. If everything checks out, a json packet is returned:
+[code nowrap]
+ {
+ "success":1,
+ "confirm":"q0Ysovd1uQRsur2xG9Tg6bC23ynzw0191SkVd7CJcYoaePy6e_v0vnmPg2xBUtIaHpx_aSuhgAkd3aVjPeaVBmts6aakT6a_yAEy7l2rBydntu2tvrHhoVqRNOmw0Q1tI6hwobk1BgK9Pm0lwOeAo8Q98BqIJxf47yO9pATa0wktOg6a7LMogC2zkkhwOV5oEqjJfeHeo27TiHr1e2WaphfCusjmk27V_FAYTzw05HvW4SPCx55EeeTJYIwDfQwjLfP4aKV-I8HQCINt-2yxJvzH7Izy9AW-7rYU0Il_gW5hrhIS5MTM12GBXLVs2Ij1CCLXIs4cO0x6e8KEIKwIjf7iAu60JPmnb_fx4QgBlF2HLw9vXMwZokor8yktESoGl1nvf5VV5GHWSIKAur3KPS2Tb0ekNh-tIk9u-xob4d9eIf6tge_d3aq1LcAtrDBDLk8AD0bho5zrVuTmZ9k-lBVPr_DRHSV_dlpu088j3ThaBsuV1olHK3vLFRhYCDIO0CqqK5IuhqtRNnRaqhlNN6fQUHpXk2SwHiJ2W36RCYMTnno6ezFk_tN-RA2ly-FomNZoC5FPA9gFwoJR7ZmVFDmUeK3bW-zYTA5vu15lpBPnt7Up_5rZKkr0WQVbhWJmylqOuwuNWbn3SrMQ8rYFZ23Tv300cOfKVgRBaePWQb4"
+ }
+[/code]
+'confirm' in this case is the base64url encoded RSA signature of the concatenation of 'secret' with the base64url encoded whirlpool hash of the source guid and guid_sig; signed with the source channel private key. This prevents a man-in-the-middle from inserting a rogue success packet. Upon receipt and successful verification of this packet, the destination site will redirect to the original destination URL and indicate a successful remote login.
+
+[h3]Zot Structures[/h3]
+[h4]Zot Signatures[/h4]
+All signed data in Zot is accomplished by performing an RSA sign operation using the private key of the initiator. The binary result is then base64url encoded for transport.
+[h4]Zot Encryption[/h4]
+Encryption is currently provided by AES256-CBC, the Advanced Encryption Standard using 256-bit keys and the Cipher Block Chaining mode of operation. Additional algorithms MAY be supported. A 32-octet key and 16-octet initialisation vector are randomly generated. The desired data is then encrypted using these generated strings and the result base64url encoded. Then we build an array:
+
+[dl terms="b"]
+[*= data]The base64url encoded encrypted data
+[*= alg]The chosen algorithm, in this case the string 'aes256cbc'.
+[*= key]The randomly generated key, RSA encrypted using the recipients public key, and the result base64url encoded
+[*= iv]The randomly generated initialization vector, RSA encrypted using the recipient's public key, and the result base64url encoded
+[/dl]
+
+[h4]Basic Zot Packet[/h4]
+Used for initiating a dialogue with another Zot site. This packet MAY be encrypted. The presence of an array element 'iv' indicates encryption has been applied. When sending an 'auth_check' packet type, this packet MUST be encrypted, using the public key of the destination site (the site key, as opposed to a sender key).
+
+[code nowrap]
+ {
+ "type":"notify",
+ "sender":{
+ "guid":"kgVFf_1_SSbyqH-BNWjWuhAvJ2EhQBTUdw-Q1LwwssAntr8KTBgBSzNVzUm9_RwuDpxI6X8me_QQhZMf7RfjdA",
+ "guid_sig":"PT9-TApzpm7QtMxC63MjtdK2nUyxNI0tUoWlOYTFGke3kNdtxSzSvDV4uzq_7SSBtlrNnVMAFx2_1FDgyKawmqVtRPmT7QSXrKOL2oPzL8Hu_nnVVTs_0YOLQJJ0GYACOOK-R5874WuXLEept5-KYg0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD-yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q",
+ "url":"http:\/\/podunk.edu",
+ "url_sig":"T8Bp7j5DHHhQDCFcAHXfuhUfGk2P3inPbImwaXXF1xJd3TGgluoXyyKDx6WDm07x0hqbupoAoZB1qBP3_WfvWiJVAK4N1FD77EOYttUEHZ7L43xy5PCpojJQmkppGbPJc2jnTIc_F1vvGvw5fv8gBWZvPqTdb6LWF6FLrzwesZpi7j2rsioZ3wyUkqb5TDZaNNeWQrIEYXrEnWkRI_qTSOzx0dRTsGO6SpU1fPWuOOYMZG8Nh18nay0kLpxReuHCiCdxjXRVvk5k9rkcMbDBJcBovhiSioPKv_yJxcZVBATw3z3TTE95kGi4wxCEenxwhSpvouwa5b0hT7NS4Ay70QaxoKiLb3ZjhZaUUn4igCyZM0h6fllR5I6J_sAQxiMYD0v5ouIlb0u8YVMni93j3zlqMWdDUZ4WgTI7NNbo8ug9NQDHd92TPmSE1TytPTgya3tsFMzwyq0LZ0b-g-zSXWIES__jKQ7vAtIs9EwlPxqJXEDDniZ2AJ6biXRYgE2Kd6W_nmI7w31igwQTms3ecXe5ENI3ckEPUAq__llNnND7mxp5ZrdXzd5HHU9slXwDShYcW3yDeQLEwAVomTGSFpBrCX8W77n9hF3JClkWaeS4QcZ3xUtsSS81yLrp__ifFfQqx9_Be89WVyIOoF4oydr08EkZ8zwlAsbZLG7eLXY"
+ "sitekey":"-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxTeIwXZWrw/S+Ju6gewh
+LgkKnNNe2uCUqCqMZoYgJar3T5sHCDhvXc4dDCbDkxVIaA/+V1mURtBV60a3IGjn
+OAO0W0XGGLe2ED7G5o9U8T9mVGq8Mauv0v1oQ5wIR1gEAhBavkQ2OUGuF/YKn2nj
+HlKsv9HzUAHpcDMUe3Uklc2RhQbMcnJxEgkyjCkDyrTtCZzISkTAocHvpCG1KSog
+njUZdiz9UWxvM4rCFkCJvQU4RwRZJb7GA9ul+9JrF7NvUQTx8csRP2weBk1E9yyj
+wbe187E0eVj9RXX2Mx3mYhgrTdodxLOVMSXZLg1/SMpeFFl7QBhuM0SiOPg8a7Et
+e2iNA/RD4WiUFqCDfafasRa1TOozOm7LA+08lkAh5PeQPJsJbrX0wVVft++Y+5/z
+BvcUOP73vcbz7j5hJ7HLsbQtye/UUCfODBFybuDqRM84Aet8rjZohX7vukXdMD4I
+2HuB7pjR4uIfyYr0J63ANkvbsn8LR+RnirmHrK5H/OgxxjXcfYbGEQgFxvxhF6lA
+FpMu6Do4dx3CIb6pRmZ8bjSImXexJ0BSo9n3gtrz0XYLecsYFlQ9+QQjm83qxyLb
+M23in0xqMVsyQvzjNkpImrO/QdbEFRIIMee83IHq+adbyjQR49Z2hNEIZhkLPc3U
+2cJJ2HkzkOoF2K37qwIzk68CAwEAAQ==
+-----END PUBLIC KEY-----
+"
+ },
+ "recipients":{
+ {
+ "guid":"lql-1VnxtiO4-WF0h72wLX1Fu8szzHDOXgQaTbELwXW77k8AKFfh-hYr70vqMrc3SSvWN-Flrc5HFhRTWB7ICw",
+ "guid_sig":"PafvEL0VpKfxATxlCqDjfOeSIMdmpr3iU7X-Sysa1h5LzDpjSXsjO37tYZL-accb1M5itLlfnW5epkTa5I4flsW21zSY1A2jCuBQUTLLGV7rNyyBy7lgqJUFvAMRx0TfXzP9lcaPqlM9T1tA6jfWOsOmkdzwofGeXBnsjGfjsO2xdGYe6vwjOU0DSavukvzDMnOayB9DekpvDnaNBTxeGLM45Skzr7ZEMcNF7TeXMbnvpfLaALYEKeQs9bGH-UgAG8fBWgzVAzeBfx_XSR1rdixjyiZGP0kq0h35SlmMPcEjliodOBFwMXqpXFB7Ibp4F6o6te2p2ErViJccQVG8VNKB6SbKNXY6bhP5zVcVsJ-vR-p4xXoYJJvzTN7yTDsGAXHOLF4ZrXbo5yi5gFAlIrTLAF2EdWQwxSGyLRWKxG8PrDkzEzX6cJJ0VRcLh5z6OI5QqQNdeghPZbshMFMJSc_ApCPi9_hI4ZfctCIOi3T6bdgTNKryLm5fhy_eqjwLAZTGP-aUBgLZpb1mf2UojBn6Ey9cCyq-0T2RWyk-FcIcbV4qJ-p_8oODqw13Qs5FYkjLr1bGBq82SuolkYrXEwQClxnrfKa4KYc2_eHAXPL01iS9zVnI1ySOCNJshB97Odpooc4wk7Nb2Fo-Q6THU9zuu0uK_-JbK7IIl6go2qA"
+ },
+ },
+ "callback":"\/post",
+ "version":"1.2",
+ "encryption":{
+ "aes256cbc"
+ },
+ "secret":"1eaa6613699be6ebb2adcefa5379c61a3678aa0df89025470fac871431b70467",
+ "secret_sig":"0uShifsvhHnxnPIlDM9lWuZ1hSJTrk3NN9Ds6AKpyNRqf3DUdz81-Xvs8I2kj6y5vfFtm-FPKAqu77XP05r74vGaWbqb1r8zpWC7zxXakVVOHHC4plG6rLINjQzvdSFKCQb5R_xtGsPPfvuE24bv4fvN4ZG2ILvb6X4Dly37WW_HXBqBnUs24mngoTxFaPgNmz1nDQNYQu91-ekX4-BNaovjDx4tP379qIG3-NygHTjFoOMDVUvs-pOPi1kfaoMjmYF2mdZAmVYS2nNLWxbeUymkHXF8lT_iVsJSzyaRFJS1Iqn7zbvwH1iUBjD_pB9EmtNmnUraKrCU9eHES27xTwD-yaaH_GHNc1XwXNbhWJaPFAm35U8ki1Le4WbUVRluFx0qwVqlEF3ieGO84PMidrp51FPm83B_oGt80xpvf6P8Ht5WvVpytjMU8UG7-js8hAzWQeYiK05YTXk-78xg0AO6NoNe_RSRk05zYpF6KlA2yQ_My79rZBv9GFt4kUfIxNjd9OiV1wXdidO7Iaq_Q"
+ }
+[/code]
+
+[dl terms="b"]
+[*= type] The message type: [b]notify, purge, refresh, force_refresh, auth_check, ping[/b] or [b]pickup[/b]. The packet contents vary by message type. Here we will describe the [b]notify[/b] packet.
+[*= callback]A string to be appended onto the url which identifies the Zot communications endpoint on this system. It is typically the string "/post".
+[*= version]The Zot protocol identifier, to allow future protocol revisions to co-exist.
+[*= encryption] array of supported encryption algorithms, order by decreasing preference. If no compatible encryption methods are provided, applications MUST use 'aes256cbc'.
+[*= secret]A 64-char string which is randomly generated by the sending site.
+[*= secret_sig]The RSA signature of the secret, signed with the sender's private key.
+[*= sender] An array of four components that provide a portable identity. We can contact the URL provided and download a Zot info packet to obtain the public key of the sender, and use that to verify the sender guid and the posting URL signatures.
+ [dl terms="b"]
+ [*= guid]Typically a 64 character base64url encoded string. This is generated when an identity is created and an attempt is made that it be unique; though this isn't required.
+ [*= guid_sig]The RSA signature of the guid, signed by the sender's private key and base64url encoded.
+ [*= url]The base url of the location this post is originating from.
+ [*= url_sig]The RSA signature of url, signed by the sender's private key and base64url encoded.
+ [*= sitekey]The public key of the website specified in the url
+ [/dl]
+[*= recipients] Only used for private messages. An array of envelope recipients. Each recipient is represented by an array of guid and guid_sig. When recipients are specified, the entire packet is also encapsulated using a negotiated cryptographic algorithm or 'aes256cbc' if none could be negotiated.
+ [dl terms="b"]
+ [*= guid]The guid of a private recipient.
+ [*= guid_sig]The RSA signature of the guid, signed by the recipient's private key and base64url encoded
+ [/dl]
+[/dl]
diff --git a/doc/hook/stream_item.bb b/doc/hook/stream_item.bb
new file mode 100644
index 000000000..30086961d
--- /dev/null
+++ b/doc/hook/stream_item.bb
@@ -0,0 +1,13 @@
+[h2]stream_item[/h2]
+
+
+Called for each item processed for viewing by conversation();
+
+The hook data consists of an array
+
+ array(
+ 'mode' => current mode of conversation()
+ 'item' => item being processed
+ );
+
+ Set item['blocked'] to block the item from viewing. This action will not affect comment or sub-thread counts, so if there are three comments in a conversation and you block one, three comments will still be reported even though only two are visible.
diff --git a/doc/hook/zot_best_algorithm.bb b/doc/hook/zot_best_algorithm.bb
new file mode 100644
index 000000000..ccde505cb
--- /dev/null
+++ b/doc/hook/zot_best_algorithm.bb
@@ -0,0 +1,3 @@
+[h2]zot_best_algorithm[/h2]
+
+
diff --git a/doc/hooklist.bb b/doc/hooklist.bb
index 52af9608c..863824590 100644
--- a/doc/hooklist.bb
+++ b/doc/hooklist.bb
@@ -542,6 +542,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/smilie]smilie[/zrl]
Called when translating emoticons
+[zrl=[baseurl]/help/hook/stream_item]stream_item[/zrl]
+ Called for each item which is rendered for viewing via conversation()
+
[zrl=[baseurl]/help/hook/tagged]tagged[/zrl]
Called when a delivery is processed which results in you being tagged
@@ -554,6 +557,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/well_known]well_known[/zrl]
Called when accessing the '.well-known' special site addresses
+[zrl=[baseurl]/help/hook/zot_best_algorithm]zot_best_algorithm[/zrl]
+ Called when negotiating crypto algorithms with remote sites
+
[zrl=[baseurl]/help/hook/zid]zid[/zrl]
Called when adding the observer's zid to a URL
diff --git a/doc/member/assets/qr_text_to_post.png b/doc/member/assets/qr_text_to_post.png
new file mode 100644
index 000000000..887c85492
--- /dev/null
+++ b/doc/member/assets/qr_text_to_post.png
Binary files differ
diff --git a/doc/member/assets/zat_dialog.png b/doc/member/assets/zat_dialog.png
new file mode 100644
index 000000000..892964e95
--- /dev/null
+++ b/doc/member/assets/zat_dialog.png
Binary files differ
diff --git a/doc/member/bbcode.html b/doc/member/bbcode.html
new file mode 100644
index 000000000..99d0ce6bc
--- /dev/null
+++ b/doc/member/bbcode.html
@@ -0,0 +1,316 @@
+<style>
+ section {
+ display: inline-block;
+ overflow-x: scroll;
+ }
+</style>
+<h3>Text Decoration</h3>
+<table class="table table-responsive table-bordered">
+ <tbody>
+ <tr>
+ <th>BBcode syntax</th><th>Rendered text</th>
+ </tr>
+ <tr>
+ <td><code>[b]bold[/b]</code></td><td><strong>bold</strong></td>
+ </tr>
+ <tr>
+ <td><code>[i]italic[/i]</code></td><td><em>italic</em></td>
+ </tr>
+ <tr>
+ <td><code>[u]underlined[/u]</code></td><td><u>underlined</u></td>
+ </tr>
+ <tr>
+ <td><code>[s]strike[/s]</code></td><td><strike>strike</strike></td>
+ </tr>
+ <tr>
+ <td><code>[color=red]red[/color]</code></td><td><span style="color: red;">red</span></td>
+ </tr>
+ <tr>
+ <td><code>[font=courier]some text[/font] </code></td><td><span style="font-family: courier;">some text</span></td>
+ </tr>
+ <tr>
+ <td><code>[quote]quote[/quote]</code></td><td><blockquote>quote</blockquote></td>
+ </tr>
+ <tr>
+ <td><code>[quote=Author]Author? Me? No, no, no...[/quote]</code></td><td><strong class="author">Author wrote:</strong><blockquote>Author? Me? No, no, no...</blockquote></td>
+ </tr>
+ <tr>
+ <td><code>
+ [size=small]small text[/size]<br>
+ [size=xx-large]xx-large text[/size]<br>
+ [size=20]20px exactly[/size]<br>
+ </code>
+ Size options include: <strong>xx-small, small, medium, large, xx-large</strong></td><td><span style="font-size: small;">small text</span><br><span style="font-size: xx-large;">xx-large text</span><br><span style="font-size: 20px;">20px exactly</span></td>
+ </tr>
+ <tr>
+ <td><code>Add a horizontal bar
+[hr]
+Like this
+ </code></td><td>
+ Add a horizontal bar<br><hr><br>Like this
+ </td>
+ </tr>
+ <tr>
+ <td><code>This is
+[center]centered[/center]
+text</code></td><td>
+ This is<br><div style="text-align:center;">centered</div><br>text
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h3>Code blocks</h3>
+Code can be rendered generically in a block or inline format (depending on if there are new line characters in the text), or you can specify a supported language for enhanced syntax highlighting. Supported languages include <strong>php, css, mysql, sql, abap, diff, html, perl, ruby, vbscript, avrc, dtd, java, xml, cpp, python, javascript, js, json, sh </strong>.
+<br><br>
+<table class="table table-responsive table-bordered">
+ <tbody>
+ <tr>
+ <th>BBcode syntax</th><th>Output</th>
+ </tr>
+ <tr>
+ <td><code>[code]function bbcode() { }[/code]</code></td><td><code>function bbcode() { }</code></td>
+ </tr>
+ <tr>
+ <td><code>[code=php]function bbcode() {<br>
+ $variable = true;<br>
+ if( $variable ) {<br>
+ echo "true";<br>
+ }<br>
+}[/code]</code></td><td><code><div class="hl-main"><ol class="hl-main"><li><span class="hl-code">&nbsp;</span><span class="hl-reserved">function</span><span class="hl-code"> </span><span class="hl-identifier">bbcode</span><span class="hl-brackets">(</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"></span></li><li><span class="hl-code">&nbsp;&nbsp;&nbsp;</span><span class="hl-var">$variable</span><span class="hl-code"> = </span><span class="hl-reserved">true</span><span class="hl-code">;</span></li><li><span class="hl-code">&nbsp;&nbsp;&nbsp;</span><span class="hl-reserved">if</span><span class="hl-brackets">(</span><span class="hl-code"> </span><span class="hl-var">$variable</span><span class="hl-code"> </span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-brackets">{</span><span class="hl-code"></span></li><li><span class="hl-code">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="hl-reserved">echo</span><span class="hl-code"> </span><span class="hl-quotes">"</span><span class="hl-string">true</span><span class="hl-quotes">"</span><span class="hl-code">;</span></li><li><span class="hl-code">&nbsp;&nbsp;&nbsp;</span><span class="hl-brackets">}</span><span class="hl-code"></span></li><li><span class="hl-code">&nbsp;</span><span class="hl-brackets">}</span></li></ol></div></code></td>
+ </tr>
+ <tr>
+ <td><code>[nobb][nobb]This is how [i]you[/i] can
+[u]show[/u] how to use
+[hl]BBcode[/hl] syntax[/nobb][/nobb]</code></td><td>[nobb]This is how [i]you[/i] can [u]show[/u] how to use [hl]BBcode[/hl] syntax[/nobb]</td>
+ </tr>
+ </tbody>
+</table>
+
+<h3>Lists</h3>
+<table class="table table-responsive table-bordered">
+ <tbody>
+ <tr>
+ <th>BBcode syntax</th><th>Rendered list</th>
+ </tr>
+ <tr>
+ <td><code>[ul]<br>
+[*] First list element<br>
+[*] Second list element<br>
+[/ul]</code></td><td><ul class="listbullet" style="list-style-type: circle;"><li> First list element</li><li> Second list element<br></li></ul></td>
+ </tr>
+ <tr>
+ <td><code>[ol]<br>
+[*] First list element<br>
+[*] Second list element<br>
+[/ol]</code></td><td><ul class="listdecimal" style="list-style-type: decimal;"><li> First list element</li><li> Second list element<br></li></ul></td>
+ </tr>
+ <tr>
+ <td><code>[list=A]<br>
+[*] First list element<br>
+[*] Second list element<br>
+[/list]</code>
+ The list type options are <code>1, i, I, a, A</code>.</td><td><ul class="listupperalpha" style="list-style-type: upper-alpha;"><li> First list element</li><li> Second list element</li></ul></td>
+ </tr>
+ <tr>
+ <td><code>[dl terms="b"]<br>
+[*= First element term] First element description<br>
+[*= Second element term] Second element description<br>
+[/dl]</code>
+ The <strong>terms</strong> style options can be any combination of:
+ <dl class="bb-dl dl-horizontal">
+ <dt>b</dt><dd>bold</dd>
+ <dt>i</dt><dd>italic</dd>
+ <dt>u</dt><dd>underline</dd>
+ <dt>m</dt><dd>monospace</dd>
+ <dt>l</dt><dd>large</dd>
+ <dt>h</dt><dd>horizontal &mdash; like <em>this</em> defintion list</dd>
+ </dl>
+ </td><td><dl class="bb-dl dl-terms-bold">
+<dt> First element term</dt><dd> First element description<br></dd>
+<dt> Second element term</dt><dd> Second element description<br></dd></dl></td>
+ </tr>
+ </tbody>
+</table>
+
+<h3>Tables</h3>
+
+<table class="table table-responsive table-bordered">
+ <tbody>
+ <tr>
+ <th>BBcode syntax</th><th>Rendered table</th>
+ </tr>
+ <tr>
+ <td><code>[table border=0]<br>
+[tr]<br>
+[th]Header 1[/th][th]Header 2[/th]<br>
+[/tr]<br>
+[tr][td]Content[/td][td]Content[/td][/tr]<br>
+[tr][td]Content[/td][td]Content[/td][/tr]<br>
+[/table]</code></td><td><table class="table table-responsive"><tbody><tr><th>Header 1</th><th>Header 2</th></tr>
+<tr><td>Content</td><td>Content</td></tr><tr><td>Content</td><td>Content</td></tr></tbody></table></td>
+ </tr>
+ <tr>
+ <td><code>[table border=1]<br>
+[tr]<br>
+[th]Header 1[/th][th]Header 2[/th]<br>
+[/tr]<br>
+[tr][td]Content[/td][td]Content[/td][/tr]<br>
+[tr][td]Content[/td][td]Content[/td][/tr]<br>
+[/table]</code></td><td><table class="table table-responsive table-bordered"><tbody><tr><th>Header 1</th><th>Header 2</th></tr>
+<tr><td>Content</td><td>Content</td></tr><tr><td>Content</td><td>Content</td></tr></tbody></table></td>
+ </tr>
+ <tr>
+ <td><code>[table]<br>
+[tr]<br>
+[th]Header 1[/th][th]Header 2[/th]<br>
+[/tr]<br>
+[tr][td]Content[/td][td]Content[/td][/tr]<br>
+[tr][td]Content[/td][td]Content[/td][/tr]<br>
+[/table]</code></td><td><table><tbody><tr><th>Header 1</th><th>Header 2</th></tr><tr><td>Content</td><td>Content</td></tr><tr><td>Content</td><td>Content</td></tr></tbody></table>
+</td>
+ </tr>
+ </tbody>
+</table>
+
+<h3>Links and Embedded Content</h3>
+
+<table class="table table-responsive table-bordered">
+ <tbody>
+ <tr>
+ <th>BBcode syntax</th><th>Output</th>
+ </tr>
+ <tr>
+ <td><code>[video]video URL[/video]<br>
+[audio]audio URL[/audio]</code></td><td></td>
+ </tr>
+ <tr>
+ <td><code>[url=https://hubzilla.org]Hubzilla[/url]</code></td><td><a href="https://hubzilla.org" target="_blank">Hubzilla</a></td>
+ </tr>
+ <tr>
+ <td><code>An image [img]url/of/image.jpg[/img]
+in some text </code></td><td>
+ An image <img src="/images/default_profile_photos/rainbow_man/48.jpg" alt="Image/photo"> in some text
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+
+<h3>$Projectname specific codes</h3>
+
+<table class="table table-responsive table-bordered">
+ <tbody>
+ <tr>
+ <th>BBcode syntax</th><th>Output</th>
+ </tr>
+ <tr>
+ <td>Magic-auth version of [url] tag
+ <code>[zrl=https://hubzilla.org]Identity-aware link[/zrl]</code>
+ </td><td><code>https://hubzilla.org/?zid=[observer=1][observer.address][/observer][observer=0]your_channel@your.home.hub[/observer]</code></td>
+ </tr>
+ <tr>
+ <td>Magic-auth version of [img] tag
+ <code>[zmg]https://hubzilla.org/some/photo.jpg[/zmg]</code>
+ </td><td>Image is only viewable by those authenticated and with permission.</td>
+ </tr>
+ <tr>
+ <td>Observer-dependent output:<code>
+ [nobb][observer=1]Text to display if observer IS authenticated[/observer][/nobb]
+ </code></td><td></td>
+ </tr>
+ <tr>
+ <td>
+ <code>
+ [nobb][observer=0]Text to display if observer IS NOT authenticated[/observer][/nobb]
+ </code>
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>
+ <code>
+ [nobb][observer.url][/nobb]
+ </code>
+ </td>
+ <td>channel URL of observer</td>
+ </tr>
+ <tr>
+ <td>
+ <code>
+ [nobb][observer.baseurl][/nobb]
+ </code>
+ </td>
+ <td>website of observer</td>
+ </tr>
+ <tr>
+ <td>
+ <code>
+ [nobb][observer.name][/nobb]
+ </code>
+ </td>
+ <td>name of observer</td>
+ </tr>
+ <tr>
+ <td>
+ <code>
+ [nobb][observer.webname][/nobb]
+ </code>
+ </td>
+ <td>short name in the url of the observer</td>
+ </tr>
+ <tr>
+ <td>
+ <code>
+ [nobb][observer.address][/nobb]
+ </code>
+ </td>
+ <td>address (ZOT-id) of observer</td>
+ </tr>
+ <tr>
+ <td>
+ <code>
+ [nobb][observer.photo][/nobb]
+ </code>
+ </td>
+ <td>profile photo of observer</td>
+ </tr>
+ <tr>
+ <td><code>What is a spoiler?<br>
+ [spoiler]Text you want to hide.[/spoiler]</code></td><td>
+ What is a spoiler? <div onclick="openClose('opendiv-1131603764'); return false;" class="fakelink">Click to open/close</div><blockquote id="opendiv-1131603764" style="display: none;">Text you want to hide.</blockquote>
+ </td>
+ </tr>
+ <tr>
+ <td><code>[toc data-toc='div.page-body' data-toc-headings='h1,h2']</code><br>
+Create a table of content in a webpage or wiki page. Please refer to the <a href="http://ndabas.github.io/toc/" target="_blank">original jQuery toc</a> to get more explanations.
+ <ul>
+ <li>Optional param: 'data-toc'. If omitted the default is 'body'</li>
+ <li>Optional param: 'data-toc-headings'. If omitted the default is 'h1,h2,h3'</li>
+ </ul></td><td></td>
+ </tr>
+ <tr>
+ <td><code>[nobb][rpost=title]Text to post[/rpost][/nobb]</code><br>
+The observer will be returned to their home hub to enter a post with the specified title and body. Both are optional</td><td><a href="[baseurl]/rpost?f=&amp;title=title&amp;body=Text+to+post" target="_blank">[baseurl]/rpost?f=&amp;title=title&amp;body=Text+to+post</a></td>
+ </tr>
+ <tr>
+ <td>This requires the <a href="https://github.com/redmatrix/hubzilla-addons/tree/master/qrator"><strong>qrator</strong></a> plugin.<br><code>[qr]text to post[/qr]</code></td><td><img src="/doc/member/assets/qr_text_to_post.png"></td>
+ </tr>
+ <tr>
+ <td>This requires a suitable map plugin such as <strong><a href="https://github.com/redmatrix/hubzilla-addons/tree/master/openstreetmap">openstreetmap</a></strong>.
+ <code>[map]</code></td><td>Generate an inline map using the current browser coordinates of the poster, if browser location is enabled</td>
+ </tr>
+ <tr>
+ <td>This requires a suitable map plugin such as <strong><a href="https://github.com/redmatrix/hubzilla-addons/tree/master/openstreetmap">openstreetmap</a></strong>.
+ <code>[map=latitude,longitude]</code></td><td>Generate a map using global coordinates.</td></tr>
+ <tr>
+ <td>This requires a suitable map plugin such as <strong><a href="https://github.com/redmatrix/hubzilla-addons/tree/master/openstreetmap">openstreetmap</a></strong>.
+ <code>[map]Place Name[/map]</code></td><td>
+Generate a map for a given named location. The first matching location is returned. For instance "Sydney" will usually return Sydney, Australia and not Sydney, Nova Scotia, Canada unless the more precise location is specified. It is highly recommended to use the post preview utility to ensure you have the correct location before submitting the post.
+</td>
+ </tr>
+ <tr>
+ <td><code>[&amp;copy;]</code></td><td> &copy; </td>
+ </tr>
+ </tbody>
+</table>
diff --git a/doc/member/member_guide.bb b/doc/member/member_guide.bb
index 53cc6b8c7..c0ded4614 100644
--- a/doc/member/member_guide.bb
+++ b/doc/member/member_guide.bb
@@ -238,7 +238,7 @@ We highly recommend that you use the "typical social network" settings when you
[*= Anybody authenticated ] This is similar to "anybody in this network" except that it can include anybody who can authenticate by any means - and therefore [i]may[/i] include visitors from other networks.
- [*=Guest Access Token] This allows you to share a file, folder, photo, album, or channel with a specific person or group of people. They don't need to be Hubzilla members. You can set an expiration for the Access Token.
+ [*=Guest Access Token] This allows you to share a file, folder, photo, album, or channel with a specific person or group of people. They don't need to be $Projectname members. You can set an expiration for the Access Token.
[*= Anybody on the internet ] Completely public. This permission will be approved for anybody at all.
[/dl]
@@ -287,6 +287,458 @@ The connection edit screen offers a slider to select a degree of friendship with
The slider on the matrix page has both a minimum and maximum value. Posts will only be shown from people who fall between this range. Affinity has no relation to permissions, and is only useful in conjunction with the affinity tool feature.
+[h3]Guest Access Tokens[/h3]
+Guest access tokens (sometimes called "Zot access tokens") allow you to share a file, folder, photo, album, or channel with a specific person or group of people who are not $Projectname members. These tokens allow you to share individual items by sending a link that includes the token in the URL; alternatively, people can actually [i]log in[/i] using the token credentials, after which they can seamlessly view whatever content has been shared with that token.
+
+To create and manage guest tokens, open the [zrl=[baseurl]/settings/tokens/]Guest Access Tokens[/zrl] settings page. A random token is generate with each page load, allowing you to create one by inputting an associated user name and optionally specifying an expiration date. Existing tokens are listed below the dialog and can be edited by selecting them or deleted by pressing the trash icon.
+
+Additional permissions may be granted to the guest token by expanding the [b]Individual Permissions[/b] options and selecting privacy settings such as [b]Can view my channel stream and posts[/b] or [b]Can chat with me[/b].
+
+[img][baseurl]/doc/member/assets/zat_dialog.png[/img]
+
+[h3]Markup Languages[/h3]
+$Projectname supports several markup languages for advanced formatting of content. The default markup language is a [url=[baseurl]/help/member/bbcode]custom variant of BBcode[/url], tailored for use in $Projectname. [url=[baseurl]/help/member/bbcode]BBcode[/url] is supported for posts, wiki pages, and web page elements. Wiki pages and webpage elements may also be written using standard Markdown.
+[table border=0]
+[tr][th]Content Type[/th][th]Supported Markup[/th][/tr]
+[tr][td]Post[/td][td][url=[baseurl]/help/member/bbcode]BBcode[/url][/td][/tr]
+[tr][td]Wiki[/td][td][url=[baseurl]/help/member/bbcode]BBcode[/url], Markdown[/td][/tr]
+[tr][td]Webpage element[/td][td][url=[baseurl]/help/member/bbcode]BBcode[/url], Markdown, HTML[/td][/tr]
+[/table]
+
+[h3]Web Pages[/h3]
+
+$Projectname enables users to create static webpages. To activate this feature, enable the [b]Web Pages[/b] feature in your [b][url=[baseurl]/settings/features/]Additional Features[/url][/b] section.
+
+Once enabled, a new tab will appear on your channel page labeled &quot;Webpages&quot;. Clicking this link will take you to the webpage editor. Pages will be accessible at [b][baseurl]/page/[observer=1][observer.webname][/observer][observer=0]channelname[/observer]/pagelinktitle[/b]
+
+The &quot;page link title&quot; box allows a user to specify the &quot;pagelinktitle&quot; of this URL. If no page link title is set, we will set one for you automatically, using the message ID of the item.
+
+Beneath the page creation box, a list of existing pages will appear with an &quot;edit&quot; link. Clicking this will take you to an editor, similar to that of the post editor, where you can make changes to your webpages.
+
+[h4]Using Blocks[/h4]
+
+Blocks can be parts of webpages. The basic HTML of a block looks like this
+[code]
+ <div>
+ Block Content
+ </div>
+
+[/code]
+
+If a block has text/html content type it can also contain menu elements. Sample content of
+[code]
+ <p>HTML block content</p>
+ [menu]menuname[/menu]
+
+[/code]
+will produce HTML like this
+[code]
+ <div>
+ <p>HTML block content</p>
+ <div>
+ <ul>
+ <li><a href="#">Link 1</a></li>
+ <li><a href="#">Link 2</a></li>
+ <li><a href="#">Link 3</a></li>
+ </ul>
+ </div>
+ </div>
+
+[/code]
+
+Via the $content macro a block can also contain the actual webpage content. For this create a block with only
+[code]
+ $content
+
+[/code]as content.
+
+To make a block appear in the webpage it must be defined in the page layout inside a region.
+[code]
+ [region=aside]
+ [block]blockname[/block]
+ [/region]
+
+[/code]
+
+The block appearance can be manipulated in the page layout.
+
+Custom classes can be assigned
+[code]
+ [region=aside]
+ [block=myclass]blockname[/block]
+ [/region]
+
+[/code]
+will produce this HTML
+[code]
+ <div class="myclass">
+ Block Content
+ </div>
+
+[/code]
+
+Via the wrap variable a block can be stripped off its wrapping <div></div> tag
+[code]
+ [region=aside]
+ [block][var=wrap]none[/var]blockname[/block]
+ [/region]
+
+[/code]
+will produce this HTML
+[code]
+ Block Content
+[/code]
+
+[h4]Webpage element import tool[/h4]
+
+There are two methods of importing webpage elements: uploading a zip file or referencing a local cloud files folder. Both methods require that the webpage elements are specified using a specific folder structure. The import tool makes it possible to import all the elements necessary to construct an entire website or set of websites. The goal is to accommodate external development of webpages as well as tools to simplify and automate deployment on a hub.
+
+[h5] Folder structure [/h5]
+Element definitions must be stored in the repo root under folders called
+[code]
+ /pages/
+ /blocks/
+ /layouts/
+[/code]
+
+Each element of these types must be defined in an individual subfolder using two files: one JSON-formatted file for the metadata and one plain text file for the element content.
+
+[h5] Page elements [/h5]
+Page element metadata is specified in a JSON-formatted file called [code]page.json[/code] with the following properties:
+[list]
+[*] title
+[*] pagelink
+[*] mimetype
+[*] layout
+[*] contentfile
+[/list]
+[b]Example[/b]
+
+Files:
+[code]
+ /pages/my-page/page.json
+ /pages/my-page/my-page.bbcode
+[/code]
+Content of [code]page.json[/code]:
+[code]
+ {
+ "title": "My Page",
+ "pagelink": "mypage",
+ "mimetype": "text/bbcode",
+ "layout": "my-layout",
+ "contentfile": "my-page.bbcode"
+ }
+[/code]
+[h5] Layout elements [/h5]
+
+Layout element metadata is specified in a JSON-formatted file called [code]layout.json[/code] with the following properties:
+[list]
+[*] name
+[*] description
+[*] contentfile
+[/list]
+[b]Example[/b]
+
+Files:
+[code]
+ /layouts/my-layout/layout.json
+ /layouts/my-layout/my-layout.bbcode
+[/code]
+Content of [code]layout.json[/code]:
+[code]
+ {
+ "name": "my-layout",
+ "description": "Layout for my project page",
+ "contentfile": "my-layout.bbcode"
+ }
+[/code]
+
+[h5] Block elements [/h5]
+
+Block element metadata is specified in a JSON-formatted file called [code]block.json[/code] with the following properties:
+[list]
+[*] name
+[*] title
+[*] mimetype
+[*] contentfile
+[/list]
+[b]Example[/b]
+
+Files:
+[code]
+ /blocks/my-block/block.json
+ /blocks/my-block/my-block.html
+[/code]
+Content of [code]block.json[/code]:
+
+[code]
+ {
+ "name": "my-block",
+ "title": "",
+ "mimetype": "text/html",
+ "contentfile": "my-block.html"
+ }
+[/code]
+
+[h3]Comanche Page Description Language[/h3]
+
+Comanche is a markup language similar to [url=[baseurl]/help/member/bbcode]BBcode[/url] with which to create elaborate and complex web pages by assembling them from a series of components - some of which are pre-built and others which can be defined on the fly. Comanche uses a Page Decription Language to create these pages.
+
+Comanche primarily chooses what content will appear in various regions of the page. The various regions have names and these names can change depending on what layout template you choose.
+
+[h4]Page Templates[/h4]
+Currently there are five layout templates, unless your site provides additional layouts.
+
+[dl terms="b"]
+[*= default]
+The default template defines a &quot;nav&quot; region across the top, &quot;aside&quot; as a fixed width sidebar,
+&quot;content&quot; for the main content region, and &quot;footer&quot; for a page footer.
+
+[*= full]
+The full template defines the same as the default template with the exception that there is no &quot;aside&quot; region.
+
+[*= choklet]
+The choklet template provides a number of fluid layout styles which can be specified by flavour:
+[list]
+[*] (default flavour) - a two column layout similar to the "default" template, but more fluid
+[*] bannertwo - a two column layout with a banner region, compatible with the "default" template on small displays
+[*] three - three column layout (adds a "right_aside" region to the default template)
+[*] edgestwo - two column layout with fixed side margins
+[*] edgesthree - three column layout with fixed side margins
+[*] full - three column layout with fixed side margins and adds a "header" region beneath the navigation bar
+[/list]
+
+[*= redable]
+A template for reading longer texts full screen (so without navigation bar). Three columns: aside, content and right_aside.
+For maximum readability it is advised to only use the middle content column.
+
+[*= zen]
+Gives you the freedom to do everything yourself. Just a blank page with a content region.
+[/dl]
+
+To choose a layout template, use the 'template' tag.
+
+[code]
+ [template]full[/template]
+
+[/code]
+
+To choose the "choklet" template with the "three" flavour:
+
+[code]
+ [template=three]choklet[/template]
+
+[/code]
+
+The default template will be used if no other template is specified. The template can use any names it desires for content regions. You will be using 'region' tags to decide what content to place in the respective regions.
+
+Three &quot;macros&quot; have been defined for your use.
+[code]
+ $htmlhead - replaced with the site head content.
+ $nav - replaced with the site navigation bar content.
+ $content - replaced with the main page content.
+
+[/code]
+
+By default, $nav is placed in the &quot;nav&quot; page region and $content is placed in the &quot;content&quot; region. You only need to use these macros if you wish to re-arrange where these items appear, either to change the order or to move them to other regions.
+
+
+To select a theme for your page, use the 'theme' tag.
+[code]
+ [theme]suckerberg[/theme]
+
+[/code]
+This will select the theme named &quot;suckerberg&quot;. By default your channel's preferred theme will be used.
+
+[code]
+ [theme=passion]suckerberg[/theme]
+
+[/code]
+This will select the theme named &quot;suckerberg&quot; and select the &quot;passion&quot; schema (theme variant). Alternatively it may be possible to use a condensed theme notation for this.
+
+[code]
+ [theme]suckerberg:passion[/theme]
+
+[/code]
+
+The condensed notation isn't part of Comanche itself but is recognised by $Projectname platform as a theme specifier.
+
+[h4]Regions[/h4]
+Each region has a name, as noted above. You will specify the region of interest using a 'region' tag, which includes the name. Any content you wish placed in this region should be placed between the opening region tag and the closing tag.
+
+[code]
+ [region=htmlhead]....content goes here....[/region]
+ [region=aside]....content goes here....[/region]
+ [region=nav]....content goes here....[/region]
+ [region=content]....content goes here....[/region]
+
+[/code]
+
+[h4]CSS and Javascript[/h4]
+We have the possibility to include javascript and css libraries in the htmlhead region. At present we make use of jquery (js), bootstrap (css/js) and foundation (css/js).
+This will overwrite the selected themes htmlhead.
+
+[code]
+ [region=htmlhead]
+ [css]bootstrap[/css]
+ [js]jquery[/js]
+ [js]bootstrap[/js]
+ [/region]
+
+[/code]
+
+[h4]Menus and Blocks[/h4]
+Your webpage creation tools allow you to create menus and blocks, in addition to page content. These provide a chunk of existing content to be placed in whatever regions and whatever order you specify. Each of these has a name which you define when the menu or block is created.
+
+[code]
+ [menu]mymenu[/menu]
+
+[/code]
+This places the menu called &quot;mymenu&quot; at this location on the page, which must be inside a region.
+
+[code]
+ [menu=horizontal]mymenu[/menu]
+
+[/code]
+This places the menu called &quot;mymenu&quot; at this location on the page, which must be inside a region. Additionally it applies the "horizontal" class to the menu. "horizontal" is defined in the redbasic theme. It may or may not be available in other themes.
+
+[code]
+ [menu][var=wrap]none[/var]mymenu[/menu]
+
+[/code]
+The variable [var=wrap]none[/var] in a block removes the wrapping div element from the menu.
+
+[code]
+ [block]contributors[/block]
+[/code]
+This places a block named &quot;contributors&quot; in this region.
+
+[code]
+ [block=someclass]contributors[/block]
+
+[/code]
+This places a block named &quot;contributors&quot; in this region. Additionally it applies the &quot;someclass&quot; class to the block. This replaces the default block classes &quot;bblock widget&quot;.
+
+[code]
+ [block][var=wrap]none[/var]contributors[/block]
+
+[/code]
+The variable [var=wrap]none[/var] in a block removes the wrapping div element from the block.
+
+[h4]Widgets[/h4]
+Widgets are executable apps provided by the system which you can place on your page. Some widgets take arguments which allows you to tailor the widget to your purpose. (TODO: list available widgets and arguments). The base system provides
+
+[code]
+ profile - widget which duplicates the profile sidebar of your channel page. This widget takes no arguments
+ tagcloud - provides a tag cloud of categories
+ count - maximum number of category tags to list
+
+[/code]
+
+Widgets and arguments are specified with the 'widget' and 'var' tags.
+[code]
+ [widget=recent_visitors][var=count]24[/var][/widget]
+
+[/code]
+
+This loads the &quot;recent_visitors&quot; widget and supplies it with the argument &quot;count&quot; set to &quot;24&quot;.
+
+[h4]Comments[/h4]
+The 'comment' tag is used to delimit comments. These comments will not appear on the rendered page.
+
+[code]
+ [comment]This is a comment[/comment]
+
+[/code]
+
+[h4]Conditional Execution[/h4]
+You can use an 'if' construct to make decisions. These are currently based on system configuration variable or the current observer.
+
+[code]
+ [if $config.system.foo]
+ ... the configuration variable system.foo evaluates to 'true'.
+ [else]
+ ... the configuration variable system.foo evaluates to 'false'.
+ [/if]
+
+ [if $observer]
+ ... this content will only be show to authenticated viewers
+ [/if]
+
+[/code]
+
+ The 'else' clause is optional.
+
+ Several tests are supported besides boolean evaluation.
+
+[code]
+ [if $config.system.foo == bar]
+ ... the configuration variable system.foo is equal to the string 'bar'
+ [/if]
+ [if $config.system.foo != bar]
+ ... the configuration variable system.foo is not equal to the string 'bar'
+ [/if]
+ [if $config.system.foo {} bar ]
+ ... the configuration variable system.foo is a simple array containing a value 'bar'
+ [/if]
+ [if $config.system.foo {*} bar]
+ ... the configuration variable system.foo is a simple array containing a key named 'bar'
+ [/if]
+[/code]
+
+[h4]Complex Example[/h4]
+[code]
+ [comment]use an existing page template which provides a banner region plus 3 columns beneath it[/comment]
+
+ [template]3-column-with-header[/template]
+
+ [comment]Use the &quot;darknight&quot; theme[/comment]
+
+ [theme]darkknight[/theme]
+
+ [comment]Use the existing site navigation menu[/comment]
+
+ [region=nav]$nav[/region]
+
+ [region=side]
+
+ [comment]Use my chosen menu and a couple of widgets[/comment]
+
+ [menu]myfavouritemenu[/menu]
+
+ [widget=recent_visitors]
+ [var=count]24[/var]
+ [var=names_only]1[/var]
+ [/widget]
+
+ [widget=tagcloud][/widget]
+ [block]donate[/block]
+
+ [/region]
+
+
+
+ [region=middle]
+
+ [comment]Show the normal page content[/comment]
+
+ $content
+
+ [/region]
+
+
+
+ [region=right]
+
+ [comment]Show my condensed channel &quot;wall&quot; feed and allow interaction if the observer is allowed to interact[/comment]
+
+ [widget]channel[/widget]
+
+ [/region]
+
+[/code]
+
+
[h3]Personal Cloud Storage[/h3]
$Projectname provides an ability to store privately and/or share arbitrary files with friends.
@@ -320,8 +772,8 @@ RedDav using Windows 7 graphical user interface wizard:
2. Right-click the My computer icon to access its menu.
3. Left-click Map network drive... to open the connection dialog wizard.
4. Type #^[url=https://example.net/dav/your_channel_name]https://example.net/dav/your_channel_name[/url] in the textbox and click the Complete button where &quot;example.net&quot; is the URL of your hub.
-5. Type your Hubzilla account's user name. IMPORTANT - NO at-sign or domain name.
-6. Type your Hubzilla password
+5. Type your $Projectname account's user name. IMPORTANT - NO at-sign or domain name.
+6. Type your $Projectname password
[h4]Cloud Desktop Clients - Linux[/h4]
diff --git a/doc/roadmap_hz3.md b/doc/roadmap_hz3.md
new file mode 100644
index 000000000..a64fb2d5c
--- /dev/null
+++ b/doc/roadmap_hz3.md
@@ -0,0 +1,27 @@
+
+Hubzilla III
+============
+
+Due: December 2017
+Codename:
+
+
+Wishlist:
+
+- Move CalDAV/CardDAV server to core
+
+- Integrate Hubzilla events with CalDAV
+
+- Connection 'roles' allows you to select different permission roles for your connections; such as follower, friend, contributor, etc.
+
+- CardDAV integration with abook and profiles
+
+- App tray
+
+- issues manager
+
+- wiki cloning
+
+- provide easy channel move (as opposed to channel copy or clone), which is currently supported only by the basic server role.
+
+- provide RSA keychange operation; which cannot affect the primary identity (which is based on the channel keys), so add a secondary dynamic key pair which will be used for all other operations and can be upgraded or revoked at any time. \ No newline at end of file
diff --git a/doc/toc.html b/doc/toc.html
index 272f43c7e..eeb0fe437 100644
--- a/doc/toc.html
+++ b/doc/toc.html
@@ -22,6 +22,7 @@
<div id="members" class="panel-collapse collapse in">
<ul class="list-group">
<li class="doco-list-group-item"><a href="/help/member/member_guide">Guide</a></li>
+ <li class="doco-list-group-item"><a href="/help/member/bbcode">BBcode Reference</a></li>
<li class="doco-list-group-item"><a href="/help/member/member_faq">FAQ</a></li>
</ul>
</div>
@@ -48,7 +49,8 @@
<div id="developers" class="panel-collapse collapse in">
<ul class="list-group">
<li class="doco-list-group-item"><a href="/help/developer/developer_guide">Guide</a></li>
- <li class="doco-list-group-item"><a href="/help/developer/api_zot">Zot Protocol and API</a></li>
+ <li class="doco-list-group-item"><a href="/help/developer/zot_protocol">Zot Protocol</a></li>
+ <li class="doco-list-group-item"><a href="/help/developer/api_zot">Zot API</a></li>
</ul>
</div>
</div>
@@ -66,7 +68,7 @@
</div>
</div>
<script>
-
+ toc = {};
// Generate the table of contents in the side nav menu (see view/tpl/help.tpl)
$(document).ready(function () {
$(".panel-collapse.in").find('a').each(function(){
@@ -87,8 +89,29 @@
}
});
- $(document.body).trigger("sticky_kit:recalc");
+ $(document.body).trigger("sticky_kit:recalc");
+
+ toc.contentTop = [];
+ toc.edgeMargin = 20; // margin above the top or margin from the end of the page
+ toc.topRange = 200; // measure from the top of the viewport to X pixels down
+ // Set up content an array of locations
+ $('#doco-side-toc').find('a').each(function(){
+ toc.contentTop.push( $( '#'+$(this).attr('href').split('#').pop() ).offset().top );
+ });
- });
+ // adjust side menu
+ $(window).scroll(function(){
+ var winTop = $(window).scrollTop(),
+ bodyHt = $(document).height(),
+ vpHt = $(window).height() + toc.edgeMargin; // viewport height + margin
+ $.each( toc.contentTop, function(i,loc){
+ if ( ( loc > winTop - toc.edgeMargin && ( loc < winTop + toc.topRange || ( winTop + vpHt ) >= bodyHt ) ) ){
+ $('#doco-side-toc li')
+ .removeClass('selected-doco-nav')
+ .eq(i).addClass('selected-doco-nav');
+ }
+ });
+ });
+ });
</script>