Changeset 3754860
- Timestamp:
- 10/19/2026 01:44:34 PM (4 weeks ago)
- Location:
- soapbox-for-blygger
- Files:
-
- 20 edited
- 1 copied
-
tags/0.1.3 (copied) (copied from soapbox-for-blygger/trunk )
-
tags/0.1.3/readme.txt (modified) (10 diffs)
-
tags/0.1.3/soapbox-for-blygger.php (modified) (2 diffs)
-
tags/0.1.3/src/Admin/SettingsPage.php (modified) (3 diffs)
-
tags/0.1.3/src/Admin/ToolsPage.php (modified) (3 diffs)
-
tags/0.1.3/src/Mentions/Verifier.php (modified) (4 diffs)
-
tags/0.1.3/src/Plugin.php (modified) (4 diffs)
-
tags/0.1.3/src/Surface/Documents.php (modified) (1 diff)
-
tags/0.1.3/src/Surface/Locations.php (modified) (2 diffs)
-
tags/0.1.3/src/Surface/RestDocuments.php (modified) (1 diff)
-
tags/0.1.3/src/Surface/Router.php (modified) (1 diff)
-
trunk/readme.txt (modified) (10 diffs)
-
trunk/soapbox-for-blygger.php (modified) (2 diffs)
-
trunk/src/Admin/SettingsPage.php (modified) (3 diffs)
-
trunk/src/Admin/ToolsPage.php (modified) (3 diffs)
-
trunk/src/Mentions/Verifier.php (modified) (4 diffs)
-
trunk/src/Plugin.php (modified) (4 diffs)
-
trunk/src/Surface/Documents.php (modified) (1 diff)
-
trunk/src/Surface/Locations.php (modified) (2 diffs)
-
trunk/src/Surface/RestDocuments.php (modified) (1 diff)
-
trunk/src/Surface/Router.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
soapbox-for-blygger/tags/0.1.3/readme.txt
r3737840 r3754860 5 5 Tested up to: 7.1 6 6 Requires PHP: 7.4 7 Stable tag: 0.1. 27 Stable tag: 0.1.3 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 15 15 An independent implementation of the Blygger protocol; not affiliated with the Blygger project. 16 16 17 Soapbox for Blygger makes your WordPress site a publisher under the [Blygger protocol](https://blygger.org/spec/0. 3/), an open protocol for publishing on your own domain in a way other people's software can subscribe to, archive completely, and quote exactly.17 Soapbox for Blygger makes your WordPress site a publisher under the [Blygger protocol](https://blygger.org/spec/0.4/), an open protocol for publishing on your own domain in a way other people's software can subscribe to, archive completely, and quote exactly. 18 18 19 19 Once it is switched on, every post you publish also becomes an item of your **blyg**, at an address such as `https://example.com/blyg/`. For each item the plugin keeps: … … 28 28 = Before you publish = 29 29 30 **The protocol is a draft.** This plugin implements Blygger 0. 3, which is before 1.0. Its wire format may change, and the plugin will follow it. What will not change is what publishing means: every address your blyg serves is a promise to keep answering there, and a pin cannot be undone. Read "Can I undo this?" below first.30 **The protocol is a draft.** This plugin implements Blygger 0.4. Like every version before 1.0 it is a draft: its wire format may change, and the plugin will follow it. What will not change is what publishing means: every address your blyg serves is a promise to keep answering there, and a pin cannot be undone. Read "Can I undo this?" below first. 31 31 32 32 **Nothing is published until you say so.** Activating the plugin publishes nothing. You choose where the blyg lives and how it is laid out, save that, and then switch publishing on. Before you run the backfill, which is the step that puts your existing posts out, do these four things: … … 37 37 4. **Be sure of the mount path and the layout.** Both are permanent from the first item published. 38 38 39 **This is an independent implementation.** Soapbox for Blygger is not written by, endorsed by or affiliated with the authors of the Blygger protocol. The protocol's specification is at [blygger.org](https://blygger.org/spec/0. 3/).39 **This is an independent implementation.** Soapbox for Blygger is not written by, endorsed by or affiliated with the authors of the Blygger protocol. The protocol's specification is at [blygger.org](https://blygger.org/spec/0.4/). 40 40 41 41 = What it does not do = … … 83 83 = Which surface layout should I choose? = 84 84 85 **Fixed paths** (selected to begin with) serves the protocol's own file names under the mount: `feed.xml`, `items/index.json`, `items/{id}.json`. Th is is Blygger 0.3 as published, and every reader understands it. Many hosts cache addresses ending in `.json` and `.xml` aggressively, so check Site Health after you choose it; see the next question.86 87 **Templated** serves the manifest at `/blyg/blyg.json` and everything else through the WordPress REST API, at addresses the manifest names. It avoids the paths hosts cache , but it follows a construct the protocol has ruled on for version 0.4 and not yet published as part of 0.3 (the manifest locates the surface). A reader has to support that, and most do not yet: one that does not will find the manifest and then get 404s. Choose it only if you know your readers can use it.85 **Fixed paths** (selected to begin with) serves the protocol's own file names under the mount: `feed.xml`, `items/index.json`, `items/{id}.json`. These are the protocol's default paths, unchanged since 0.3, so readers of any version find them. Many hosts cache addresses ending in `.json` and `.xml` aggressively, so check Site Health after you choose it; see the next question. 86 87 **Templated** serves the manifest at `/blyg/blyg.json` and everything else through the WordPress REST API, at addresses the manifest names. It avoids the paths hosts cache. It uses the manifest-located surface, which is part of Blygger 0.4: readers built to 0.4 must follow it, and the reference client does. A reader built only to 0.3 will find the manifest and then get 404s. 88 88 89 89 The choice is permanent once the blyg has an item, so it is made by you, on the settings screen, before publishing can be switched on. … … 148 148 = What are Webmentions, and what happens if I switch them on? = 149 149 150 When another blyg quotes one of your items, answers it or forksit, that site can tell yours, by sending a Webmention. It is off by default.150 When another blyg quotes one of your items, answers it, forks it or has machine-generated text that drew on it, that site can tell yours, by sending a Webmention. It is off by default. 151 151 152 152 If you switch it on (Settings > Soapbox for Blygger > Mentions), then for each mention your site receives it fetches the sender's page and its item document, and sometimes that blyg's manifest, to check that the document really refers to your item. See "External requests" below for exactly what that involves. Verified mentions are listed under Tools > Soapbox for Blygger, for administrators. Nothing is shown to visitors, and nothing from the other site is stored except its address, its item's id and its author's published name. … … 161 161 162 162 Test it before you publish anything, and above all before you run the backfill: what is published cannot be unpublished, only withdrawn. The plugin renders each post as a logged-out visitor would see it, by running the post through `the_content` outside the main loop. A plugin that hides content only inside the loop, or only on the post's own page, may not hide it there, and the full text would then be published in the blyg. Publish a test post, open its item document from the Blyg panel in the editor, and look at what it contains. If it shows more than a visitor should see, leave that post type unticked, or exclude posts with the `soapbox_blyg_is_public` filter. 163 164 = Can I help translate it? = 165 166 Yes, at [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/soapbox-for-blygger/). The plugin ships in English; each language reaches sites as a language pack once its translations are approved there. 163 167 164 168 = Does it work on multisite? = … … 180 184 How a mention is handled. Your site answers the sender at once and looks nothing up while it does: the sender's address is resolved, checked and fetched afterwards, by a background job. That job stops after twenty seconds in all, checked between each step; one step it cannot cut short is a DNS lookup, which can take as long as your server's own resolver allows. Each sender is limited by the number of requests it makes, whether or not they are accepted. 181 185 182 Known limits. Each request is pinned to the address that was checked, which closes DNS rebinding. That needs PHP's curl extension, which nearly every host has. A site without it, or one that sends its outbound requests through a proxy (`WP_PROXY_HOST`), cannot pin a request, so it verifies no Webmentions: they are accepted and then marked as failed. The templated layout's manifest declares Blygger "0.3", because the specification does not say what a manifest that uses the 0.4 construct should declare.IPv6-only senders are refused: a sender's host must have an IPv4 address, and no address it has, in either family, may be private. WordPress only allows such requests on ports 80, 443 and 8080; a sender on another port is refused unless you add it with WordPress's `http_allowed_safe_ports` filter. A mention is believed only when its item document is at exactly the address its own blyg gives for it, written plainly: an address with `..` in it, or with characters percent-encoded that need not be, is refused. A document kept on another host than its blyg (a CDN, say) cannot be sent as the source itself; send the page that links to it, which must be on the blyg's own host. In the templated layout, your own items are at addresses only your manifest names, so a receiver that implements Blygger 0.3 alone cannot verify a mention that names one of your items as its source; a receiver that reads the manifest's templates can. That is one more reason the fixed layout is the one selected to begin with.186 Known limits. Each request is pinned to the address that was checked, which closes DNS rebinding. That needs PHP's curl extension, which nearly every host has. A site without it, or one that sends its outbound requests through a proxy (`WP_PROXY_HOST`), cannot pin a request, so it verifies no Webmentions: they are accepted and then marked as failed. IPv6-only senders are refused: a sender's host must have an IPv4 address, and no address it has, in either family, may be private. WordPress only allows such requests on ports 80, 443 and 8080; a sender on another port is refused unless you add it with WordPress's `http_allowed_safe_ports` filter. A mention is believed only when its item document is at exactly the address its own blyg gives for it, written plainly: an address with `..` in it, or with characters percent-encoded that need not be, is refused. A document kept on another host than its blyg (a CDN, say) cannot be sent as the source itself; send the page that links to it, which must be on the blyg's own host. In the templated layout, your own items are at addresses only your manifest names, so a receiver that implements Blygger 0.3 alone cannot verify a mention that names one of your items as its source; a receiver that reads the manifest's templates can. That is one more reason the fixed layout is the one selected to begin with. 183 187 184 188 Caching. The plugin states its lifetime first, and relies on caches using the first of a repeated instruction, as RFC 9111 says and Varnish does. A cache that does not follow that rule could still use a lifetime your host appends. nginx's `proxy_cache` and `fastcgi_cache` are one such case: when the host's instruction arrives as a separate `Cache-Control` header line after the plugin's, nginx uses the last line. This has not been tested with nginx in front. Site Health asks for the documents as a reader would and compares what it is given with the documents as they are now; if it is given an old copy, purge that cache and exclude the blyg's paths from it as described above. … … 261 265 == Changelog == 262 266 267 = 0.1.3 = 268 * Publishes under Blygger 0.4, the protocol's published version: every document says `"blyg": "0.4"`, in both layouts. Nothing else in them changes. Every 0.3 document is a valid 0.4 document, and readers accept any 0.x. 269 * Pinned versions say "0.4" too, so their files change by those three characters. A pin promises its content, which the content hash covers, and that is unchanged. 270 * The manifest names where the plugin's source is (`generator_url`), as 0.4 recommends. 271 * Webmentions: a mention from an item whose machine-generated text drew on one of yours now verifies, as 0.4's fourth relation ("Drew on" under Tools). 272 * With Soapbox Blyg still installed, the settings now say that "Delete all data" has been switched off and does not come back on by itself. 273 263 274 = 0.1.2 = 264 275 * The plugin is now called Soapbox for Blygger, and its folder is `soapbox-for-blygger`. It was Soapbox Blyg. Nothing a site has published moves: the blyg's addresses, its ids, its settings and its data are exactly where they were, and so are the plugin's hooks, functions and `wp blyg` commands. … … 280 291 == Upgrade Notice == 281 292 293 = 0.1.3 = 294 Moves your blyg to Blygger 0.4. No address, id or version changes. 295 282 296 = 0.1.2 = 283 297 Renamed from Soapbox Blyg. Your blyg, its addresses and its data do not move. Activate this plugin before you deactivate Soapbox Blyg, then delete Soapbox Blyg. -
soapbox-for-blygger/tags/0.1.3/soapbox-for-blygger.php
r3737840 r3754860 4 4 * Plugin URI: https://github.com/cyberscribe/soapbox-blyg 5 5 * Description: Publishes your posts as a blyg: stable ids, versions, pins and a feed that other clients can subscribe to and quote. An independent implementation of the Blygger protocol; not affiliated with the Blygger project. 6 * Version: 0.1. 26 * Version: 0.1.3 7 7 * Requires at least: 6.6 8 8 * Requires PHP: 7.4 … … 52 52 const SOAPBOX_BLYG_TEXT_DOMAIN = 'soapbox-for-blygger'; 53 53 const SOAPBOX_BLYG_GENERATOR = 'soapbox-for-blygger'; 54 const SOAPBOX_BLYG_VERSION = '0.1. 2';54 const SOAPBOX_BLYG_VERSION = '0.1.3'; 55 55 const SOAPBOX_BLYG_FILE = __FILE__; 56 56 57 57 /* 58 * Where this client's source lives, for the manifest's generator_url (spec § 6.1). Empty until59 * there is a public address to name; the key is then leftout.58 * Where this client's source lives, for the manifest's generator_url (spec §3.2, §6.1). Empty 59 * leaves the key out. 60 60 */ 61 const SOAPBOX_BLYG_GENERATOR_URL = ' ';61 const SOAPBOX_BLYG_GENERATOR_URL = 'https://github.com/cyberscribe/soapbox-blyg'; 62 62 63 63 /* -
soapbox-for-blygger/tags/0.1.3/src/Admin/SettingsPage.php
r3737840 r3754860 464 464 'fixed' => array( 465 465 __( 'Fixed paths', 'soapbox-for-blygger' ), 466 __( ' Blygger 0.3, understood by every reader. The protocol\'s own file names under the mount (feed.xml, items/index.json, items/{id}.json). Check Site Health afterwards: if your host caches them at the edge, exclude the mount path from that cache.', 'soapbox-for-blygger' ),466 __( 'The protocol\'s default paths under the mount (feed.xml, items/index.json, items/{id}.json), unchanged since 0.3: readers of any version find them. Check Site Health afterwards: if your host caches them at the edge, exclude the mount path from that cache.', 'soapbox-for-blygger' ), 467 467 ), 468 468 'templated' => array( 469 469 __( 'Templated', 'soapbox-for-blygger' ), 470 __( 'Blygger 0.4 draft (decision #51). Needs a reader that supports manifest-located surfaces; most don\'t yet. The manifest says where everything else is, and the documents are served through the REST API. Managed hosts often cache paths ending in .json and .xml for weeks, which would keep serving an item after you withdrew it; this layout avoids those paths.', 'soapbox-for-blygger' ),470 __( 'Blygger 0.4\'s manifest-located surface: the manifest says where everything else is, and the documents are served through the REST API. Readers built to 0.4 must follow it, and the reference client does; a reader built only to 0.3 finds the manifest and then gets 404s. Managed hosts often cache paths ending in .json and .xml for weeks, which would keep serving an item after you withdrew it; this layout avoids those paths.', 'soapbox-for-blygger' ), 471 471 ), 472 472 ); … … 554 554 esc_html__( 'Delete all Soapbox for Blygger data when the plugin is deleted', 'soapbox-for-blygger' ) 555 555 ); 556 $note( __( ' Kept off while Soapbox Blyg, this plugin\'s earlier name, is still installed: the two share one record of what has been published, and deleting Soapbox Blyg with this on would delete it. Delete Soapbox Blyg from the Plugins screen first.', 'soapbox-for-blygger' ) );556 $note( __( 'Switched off while Soapbox Blyg, this plugin\'s earlier name, is still installed: the two share one record of what has been published, and deleting Soapbox Blyg with this on would delete it. It does not come back on by itself: delete Soapbox Blyg from the Plugins screen, then tick this again if you want it.', 'soapbox-for-blygger' ) ); 557 557 break; 558 558 } … … 581 581 sprintf( 582 582 /* translators: 1: protocol version, 2: URL of the protocol specification */ 583 __( 'This plugin publishes under the <a href="%2$s">Blygger protocol</a>, version %1$s , which is a draft: its wire format may change before 1.0, and this plugin will follow it. What does not change is the promise you make by publishing. Every address the blyg serves is meant to keep answering, and a pinned version is served forever. Soapbox for Blygger is an independent implementation and is not affiliated with the protocol\'s authors.', 'soapbox-for-blygger' ),583 __( 'This plugin publishes under the <a href="%2$s">Blygger protocol</a>, version %1$s. Like every version before 1.0 it is a draft: its wire format may change, and this plugin will follow it. What does not change is the promise you make by publishing. Every address the blyg serves is meant to keep answering, and a pinned version is served forever. Soapbox for Blygger is an independent implementation and is not affiliated with the protocol\'s authors.', 'soapbox-for-blygger' ), 584 584 esc_html( \SoapboxBlyg\Surface\Documents::PROTOCOL ), 585 esc_url( 'https://blygger.org/spec/ 0.3/' )585 esc_url( 'https://blygger.org/spec/' . \SoapboxBlyg\Surface\Documents::PROTOCOL . '/' ) 586 586 ), 587 587 array( 'a' => array( 'href' => true ) ) -
soapbox-for-blygger/tags/0.1.3/src/Admin/ToolsPage.php
r3737840 r3754860 28 28 29 29 const PAGE = 'soapbox-blyg-tools'; 30 31 /** 32 * The user meta that records which schema problem a person has dismissed. 33 */ 34 const DISMISSED_META = 'soapbox_blyg_dismissed_problem'; 30 35 31 36 /** … … 110 115 $stamp = Schema::problem_key(); 111 116 if ( '' !== $problem && isset( $_GET['soapbox_blyg_dismiss'] ) && check_admin_referer( 'soapbox_blyg_dismiss' ) ) { 112 update_user_meta( get_current_user_id(), 'soapbox_blyg_dismissed_problem', $stamp );113 } 114 if ( '' !== $problem && ( $ours || get_user_meta( get_current_user_id(), 'soapbox_blyg_dismissed_problem', true ) !== $stamp ) ) {117 update_user_meta( get_current_user_id(), self::DISMISSED_META, $stamp ); 118 } 119 if ( '' !== $problem && ( $ours || get_user_meta( get_current_user_id(), self::DISMISSED_META, true ) !== $stamp ) ) { 115 120 echo '<div class="notice notice-error"><p>'; 116 121 echo esc_html( … … 391 396 /* translators: %s: the address of one of this site's items, as a link. Another publication's item is a fork of it. */ 392 397 'fork' => __( 'Forked from %s', 'soapbox-for-blygger' ), 398 /* translators: %s: the address of one of this site's items, as a link. Another publication's item has machine-generated text that drew on it. */ 399 'source' => __( 'Drew on %s', 'soapbox-for-blygger' ), 393 400 ); 394 401 ?> -
soapbox-for-blygger/tags/0.1.3/src/Mentions/Verifier.php
r3737840 r3754860 456 456 $fetched_from = self::address( $document_url ); 457 457 if ( $speaker . 'items/' . $id . '.json' !== $fetched_from ) { 458 // Not at the fixed address, so the origin may publish its items by template ( §16.6e).458 // Not at the fixed address, so the origin may publish its items by template (spec §6.1, §15.4). 459 459 // Its manifest says where, and is the third and last document fetched: the page, the 460 460 // item document, and this. It is asked for at the claimed origin and nowhere else, so … … 477 477 $template = isset( $manifest['body'] ) && self::is_plain( $manifest['url'] ) && self::address( $manifest['url'] ) === $speaker . 'blyg.json' ? json_decode( $manifest['body'], true ) : null; 478 478 $template = is_array( $template ) && isset( $template['item'] ) && is_string( $template['item'] ) ? $template['item'] : ''; 479 // {id} is the only expression a template may hold (URI Template level 1, spec § 16.6e).479 // {id} is the only expression a template may hold (URI Template level 1, spec §6.1). 480 480 $expanded = str_replace( '{id}', rawurlencode( $id ), $template ); 481 481 if ( false === strpos( $template, '{id}' ) || false !== strpbrk( $expanded, '{}' ) || self::address( $expanded ) !== $fetched_from ) { … … 535 535 /** 536 536 * How a document refers to one of our items, if it does (spec §15.4), in the protocol's order: 537 * a stub of it, a transclusion of it, or a fork of a pinned version of it. Only the three 538 * identity members of a reference are read; `cited` and `selector` are never consulted. 537 * a stub of it, a transclusion of it, a fork of a pinned version of it, or a generation source 538 * drawn from it. Only the identity members of a reference are read; `cited` and `selector` 539 * are never consulted. 539 540 * 540 541 * @param array $document The source's item document. 541 542 * @param string $our_url This origin's URL: its identity. 542 543 * @param string $target_id Our item's id. 543 * @return string|null stub, transclusion, fork or null.544 * @return string|null stub, transclusion, fork, source or null. 544 545 */ 545 546 private function relation( array $document, string $our_url, string $target_id ) { … … 570 571 if ( $row && (int) $row['pinned'] ) { 571 572 return 'fork'; 573 } 574 } 575 // A generation source (spec 0.4 §5.7): one of our items that machine-generated text in the 576 // document drew on. Each span of `generated` lists its sources as references; one without 577 // an origin is the sender's own item. Nothing is promised of the version, so no pin check. 578 if ( isset( $document['generated'] ) && is_array( $document['generated'] ) ) { 579 foreach ( $document['generated'] as $span ) { 580 if ( ! is_array( $span ) || ! isset( $span['sources'] ) || ! is_array( $span['sources'] ) ) { 581 continue; 582 } 583 foreach ( $span['sources'] as $entry ) { 584 if ( $names( $entry ) ) { 585 return 'source'; 586 } 587 } 572 588 } 573 589 } -
soapbox-for-blygger/tags/0.1.3/src/Plugin.php
r3737840 r3754860 36 36 37 37 /** 38 * The WP-CLI command: `wp blyg`. 39 */ 40 const CLI_COMMAND = 'blyg'; 41 42 /** 38 43 * The one instance. 39 44 * … … 203 208 204 209 if ( defined( 'WP_CLI' ) && WP_CLI ) { 205 \WP_CLI::add_command( 'blyg', Cli\Command::class );210 \WP_CLI::add_command( self::CLI_COMMAND, Cli\Command::class ); 206 211 } 207 212 } … … 239 244 * this plugin is serving from: every id and every address the site has published. Nothing in 240 245 * this plugin runs at that moment, so the setting is switched off beforehand, here, and the 241 * settings screen will not switch it on again until the earlier plugin has gone. 246 * settings screen will not switch it on again until the earlier plugin has gone. Nor does 247 * anything else: the owner ticks it again. 242 248 * 243 249 * The file is looked for only when the setting is on, so an ordinary request reads nothing extra. … … 263 269 return; 264 270 } 265 echo '<div class="notice notice-info"><p>' . esc_html__( 'Soapbox Blyg, the earlier name of Soapbox for Blygger, is still installed. It can be deleted: this plugin has taken over the same blyg, at the same addresses. Until it has gone, "Delete all data when the plugin is deleted" is kept switched off, because deleting Soapbox Blyg with that setting on would delete the record of everything this site has published.', 'soapbox-for-blygger' ) . '</p></div>';271 echo '<div class="notice notice-info"><p>' . esc_html__( 'Soapbox Blyg, the earlier name of Soapbox for Blygger, is still installed. It can be deleted: this plugin has taken over the same blyg, at the same addresses. Until it has gone, "Delete all data when the plugin is deleted" stays switched off, because deleting Soapbox Blyg with that setting on would delete the record of everything this site has published. It does not come back on by itself: after deleting Soapbox Blyg, tick it again if you want it.', 'soapbox-for-blygger' ) . '</p></div>'; 266 272 } 267 273 -
soapbox-for-blygger/tags/0.1.3/src/Surface/Documents.php
r3737840 r3754860 28 28 29 29 /** 30 * The protocol version these documents are written to (spec §3.1). 31 */ 32 const PROTOCOL = '0.3'; 30 * The protocol version these documents are written to (spec §3.1). One value for every 31 * document in both layouts, pinned versions included: a pin promises its content, which 32 * content_hash covers, not its bytes (§8). 33 */ 34 const PROTOCOL = '0.4'; 33 35 34 36 /** -
soapbox-for-blygger/tags/0.1.3/src/Surface/Locations.php
r3737840 r3754860 20 20 * The manifest is always at {origin}blyg.json: that filename is what lets a reader handed a bare 21 21 * origin find the blyg, and it is what makes the origin, and so the blyg's identity, a stable 22 * path of the site's own choosing (spec § 12.2, §16.6e). Everything past the manifest is located22 * path of the site's own choosing (spec §4, §12.2). Everything past the manifest is located 23 23 * by the manifest: 24 24 * … … 177 177 * The item a URL names, within one origin: by its page, in any spelling the item has ever had, 178 178 * or by its item document URL in the origin's current layout. This is the check a Webmention's 179 * target has to pass (spec §15.3 , §16.6e: receivers check targets against their own templates).179 * target has to pass (spec §15.3: receivers check targets against their own templates). 180 180 * 181 181 * @param Origin $origin The origin. -
soapbox-for-blygger/tags/0.1.3/src/Surface/RestDocuments.php
r3737840 r3754860 18 18 /** 19 19 * Serves the feed, the archive index, item documents and pinned versions of a templated origin 20 * from REST routes. The manifest names these URLs and readers follow it (spec § 16.6e), so the20 * from REST routes. The manifest names these URLs and readers follow it (spec §6.1), so the 21 21 * documents can sit where WordPress routes natively, away from the .json and .xml paths that 22 22 * managed hosts treat as static files and cache at the edge. -
soapbox-for-blygger/tags/0.1.3/src/Surface/Router.php
r3737840 r3754860 25 25 * 26 26 * The REST API is not used for the manifest: the protocol fixes that one filename at the origin 27 * (spec §4, § 16.6e), and {origin}blyg.json is what makes the origin's identity a path the site27 * (spec §4, §6.1), and {origin}blyg.json is what makes the origin's identity a path the site 28 28 * owns. add_feed() is not used either: it serves /feed/{name}/, and the protocol's default feed 29 29 * path is {origin}feed.xml. -
soapbox-for-blygger/trunk/readme.txt
r3737840 r3754860 5 5 Tested up to: 7.1 6 6 Requires PHP: 7.4 7 Stable tag: 0.1. 27 Stable tag: 0.1.3 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 15 15 An independent implementation of the Blygger protocol; not affiliated with the Blygger project. 16 16 17 Soapbox for Blygger makes your WordPress site a publisher under the [Blygger protocol](https://blygger.org/spec/0. 3/), an open protocol for publishing on your own domain in a way other people's software can subscribe to, archive completely, and quote exactly.17 Soapbox for Blygger makes your WordPress site a publisher under the [Blygger protocol](https://blygger.org/spec/0.4/), an open protocol for publishing on your own domain in a way other people's software can subscribe to, archive completely, and quote exactly. 18 18 19 19 Once it is switched on, every post you publish also becomes an item of your **blyg**, at an address such as `https://example.com/blyg/`. For each item the plugin keeps: … … 28 28 = Before you publish = 29 29 30 **The protocol is a draft.** This plugin implements Blygger 0. 3, which is before 1.0. Its wire format may change, and the plugin will follow it. What will not change is what publishing means: every address your blyg serves is a promise to keep answering there, and a pin cannot be undone. Read "Can I undo this?" below first.30 **The protocol is a draft.** This plugin implements Blygger 0.4. Like every version before 1.0 it is a draft: its wire format may change, and the plugin will follow it. What will not change is what publishing means: every address your blyg serves is a promise to keep answering there, and a pin cannot be undone. Read "Can I undo this?" below first. 31 31 32 32 **Nothing is published until you say so.** Activating the plugin publishes nothing. You choose where the blyg lives and how it is laid out, save that, and then switch publishing on. Before you run the backfill, which is the step that puts your existing posts out, do these four things: … … 37 37 4. **Be sure of the mount path and the layout.** Both are permanent from the first item published. 38 38 39 **This is an independent implementation.** Soapbox for Blygger is not written by, endorsed by or affiliated with the authors of the Blygger protocol. The protocol's specification is at [blygger.org](https://blygger.org/spec/0. 3/).39 **This is an independent implementation.** Soapbox for Blygger is not written by, endorsed by or affiliated with the authors of the Blygger protocol. The protocol's specification is at [blygger.org](https://blygger.org/spec/0.4/). 40 40 41 41 = What it does not do = … … 83 83 = Which surface layout should I choose? = 84 84 85 **Fixed paths** (selected to begin with) serves the protocol's own file names under the mount: `feed.xml`, `items/index.json`, `items/{id}.json`. Th is is Blygger 0.3 as published, and every reader understands it. Many hosts cache addresses ending in `.json` and `.xml` aggressively, so check Site Health after you choose it; see the next question.86 87 **Templated** serves the manifest at `/blyg/blyg.json` and everything else through the WordPress REST API, at addresses the manifest names. It avoids the paths hosts cache , but it follows a construct the protocol has ruled on for version 0.4 and not yet published as part of 0.3 (the manifest locates the surface). A reader has to support that, and most do not yet: one that does not will find the manifest and then get 404s. Choose it only if you know your readers can use it.85 **Fixed paths** (selected to begin with) serves the protocol's own file names under the mount: `feed.xml`, `items/index.json`, `items/{id}.json`. These are the protocol's default paths, unchanged since 0.3, so readers of any version find them. Many hosts cache addresses ending in `.json` and `.xml` aggressively, so check Site Health after you choose it; see the next question. 86 87 **Templated** serves the manifest at `/blyg/blyg.json` and everything else through the WordPress REST API, at addresses the manifest names. It avoids the paths hosts cache. It uses the manifest-located surface, which is part of Blygger 0.4: readers built to 0.4 must follow it, and the reference client does. A reader built only to 0.3 will find the manifest and then get 404s. 88 88 89 89 The choice is permanent once the blyg has an item, so it is made by you, on the settings screen, before publishing can be switched on. … … 148 148 = What are Webmentions, and what happens if I switch them on? = 149 149 150 When another blyg quotes one of your items, answers it or forksit, that site can tell yours, by sending a Webmention. It is off by default.150 When another blyg quotes one of your items, answers it, forks it or has machine-generated text that drew on it, that site can tell yours, by sending a Webmention. It is off by default. 151 151 152 152 If you switch it on (Settings > Soapbox for Blygger > Mentions), then for each mention your site receives it fetches the sender's page and its item document, and sometimes that blyg's manifest, to check that the document really refers to your item. See "External requests" below for exactly what that involves. Verified mentions are listed under Tools > Soapbox for Blygger, for administrators. Nothing is shown to visitors, and nothing from the other site is stored except its address, its item's id and its author's published name. … … 161 161 162 162 Test it before you publish anything, and above all before you run the backfill: what is published cannot be unpublished, only withdrawn. The plugin renders each post as a logged-out visitor would see it, by running the post through `the_content` outside the main loop. A plugin that hides content only inside the loop, or only on the post's own page, may not hide it there, and the full text would then be published in the blyg. Publish a test post, open its item document from the Blyg panel in the editor, and look at what it contains. If it shows more than a visitor should see, leave that post type unticked, or exclude posts with the `soapbox_blyg_is_public` filter. 163 164 = Can I help translate it? = 165 166 Yes, at [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/soapbox-for-blygger/). The plugin ships in English; each language reaches sites as a language pack once its translations are approved there. 163 167 164 168 = Does it work on multisite? = … … 180 184 How a mention is handled. Your site answers the sender at once and looks nothing up while it does: the sender's address is resolved, checked and fetched afterwards, by a background job. That job stops after twenty seconds in all, checked between each step; one step it cannot cut short is a DNS lookup, which can take as long as your server's own resolver allows. Each sender is limited by the number of requests it makes, whether or not they are accepted. 181 185 182 Known limits. Each request is pinned to the address that was checked, which closes DNS rebinding. That needs PHP's curl extension, which nearly every host has. A site without it, or one that sends its outbound requests through a proxy (`WP_PROXY_HOST`), cannot pin a request, so it verifies no Webmentions: they are accepted and then marked as failed. The templated layout's manifest declares Blygger "0.3", because the specification does not say what a manifest that uses the 0.4 construct should declare.IPv6-only senders are refused: a sender's host must have an IPv4 address, and no address it has, in either family, may be private. WordPress only allows such requests on ports 80, 443 and 8080; a sender on another port is refused unless you add it with WordPress's `http_allowed_safe_ports` filter. A mention is believed only when its item document is at exactly the address its own blyg gives for it, written plainly: an address with `..` in it, or with characters percent-encoded that need not be, is refused. A document kept on another host than its blyg (a CDN, say) cannot be sent as the source itself; send the page that links to it, which must be on the blyg's own host. In the templated layout, your own items are at addresses only your manifest names, so a receiver that implements Blygger 0.3 alone cannot verify a mention that names one of your items as its source; a receiver that reads the manifest's templates can. That is one more reason the fixed layout is the one selected to begin with.186 Known limits. Each request is pinned to the address that was checked, which closes DNS rebinding. That needs PHP's curl extension, which nearly every host has. A site without it, or one that sends its outbound requests through a proxy (`WP_PROXY_HOST`), cannot pin a request, so it verifies no Webmentions: they are accepted and then marked as failed. IPv6-only senders are refused: a sender's host must have an IPv4 address, and no address it has, in either family, may be private. WordPress only allows such requests on ports 80, 443 and 8080; a sender on another port is refused unless you add it with WordPress's `http_allowed_safe_ports` filter. A mention is believed only when its item document is at exactly the address its own blyg gives for it, written plainly: an address with `..` in it, or with characters percent-encoded that need not be, is refused. A document kept on another host than its blyg (a CDN, say) cannot be sent as the source itself; send the page that links to it, which must be on the blyg's own host. In the templated layout, your own items are at addresses only your manifest names, so a receiver that implements Blygger 0.3 alone cannot verify a mention that names one of your items as its source; a receiver that reads the manifest's templates can. That is one more reason the fixed layout is the one selected to begin with. 183 187 184 188 Caching. The plugin states its lifetime first, and relies on caches using the first of a repeated instruction, as RFC 9111 says and Varnish does. A cache that does not follow that rule could still use a lifetime your host appends. nginx's `proxy_cache` and `fastcgi_cache` are one such case: when the host's instruction arrives as a separate `Cache-Control` header line after the plugin's, nginx uses the last line. This has not been tested with nginx in front. Site Health asks for the documents as a reader would and compares what it is given with the documents as they are now; if it is given an old copy, purge that cache and exclude the blyg's paths from it as described above. … … 261 265 == Changelog == 262 266 267 = 0.1.3 = 268 * Publishes under Blygger 0.4, the protocol's published version: every document says `"blyg": "0.4"`, in both layouts. Nothing else in them changes. Every 0.3 document is a valid 0.4 document, and readers accept any 0.x. 269 * Pinned versions say "0.4" too, so their files change by those three characters. A pin promises its content, which the content hash covers, and that is unchanged. 270 * The manifest names where the plugin's source is (`generator_url`), as 0.4 recommends. 271 * Webmentions: a mention from an item whose machine-generated text drew on one of yours now verifies, as 0.4's fourth relation ("Drew on" under Tools). 272 * With Soapbox Blyg still installed, the settings now say that "Delete all data" has been switched off and does not come back on by itself. 273 263 274 = 0.1.2 = 264 275 * The plugin is now called Soapbox for Blygger, and its folder is `soapbox-for-blygger`. It was Soapbox Blyg. Nothing a site has published moves: the blyg's addresses, its ids, its settings and its data are exactly where they were, and so are the plugin's hooks, functions and `wp blyg` commands. … … 280 291 == Upgrade Notice == 281 292 293 = 0.1.3 = 294 Moves your blyg to Blygger 0.4. No address, id or version changes. 295 282 296 = 0.1.2 = 283 297 Renamed from Soapbox Blyg. Your blyg, its addresses and its data do not move. Activate this plugin before you deactivate Soapbox Blyg, then delete Soapbox Blyg. -
soapbox-for-blygger/trunk/soapbox-for-blygger.php
r3737840 r3754860 4 4 * Plugin URI: https://github.com/cyberscribe/soapbox-blyg 5 5 * Description: Publishes your posts as a blyg: stable ids, versions, pins and a feed that other clients can subscribe to and quote. An independent implementation of the Blygger protocol; not affiliated with the Blygger project. 6 * Version: 0.1. 26 * Version: 0.1.3 7 7 * Requires at least: 6.6 8 8 * Requires PHP: 7.4 … … 52 52 const SOAPBOX_BLYG_TEXT_DOMAIN = 'soapbox-for-blygger'; 53 53 const SOAPBOX_BLYG_GENERATOR = 'soapbox-for-blygger'; 54 const SOAPBOX_BLYG_VERSION = '0.1. 2';54 const SOAPBOX_BLYG_VERSION = '0.1.3'; 55 55 const SOAPBOX_BLYG_FILE = __FILE__; 56 56 57 57 /* 58 * Where this client's source lives, for the manifest's generator_url (spec § 6.1). Empty until59 * there is a public address to name; the key is then leftout.58 * Where this client's source lives, for the manifest's generator_url (spec §3.2, §6.1). Empty 59 * leaves the key out. 60 60 */ 61 const SOAPBOX_BLYG_GENERATOR_URL = ' ';61 const SOAPBOX_BLYG_GENERATOR_URL = 'https://github.com/cyberscribe/soapbox-blyg'; 62 62 63 63 /* -
soapbox-for-blygger/trunk/src/Admin/SettingsPage.php
r3737840 r3754860 464 464 'fixed' => array( 465 465 __( 'Fixed paths', 'soapbox-for-blygger' ), 466 __( ' Blygger 0.3, understood by every reader. The protocol\'s own file names under the mount (feed.xml, items/index.json, items/{id}.json). Check Site Health afterwards: if your host caches them at the edge, exclude the mount path from that cache.', 'soapbox-for-blygger' ),466 __( 'The protocol\'s default paths under the mount (feed.xml, items/index.json, items/{id}.json), unchanged since 0.3: readers of any version find them. Check Site Health afterwards: if your host caches them at the edge, exclude the mount path from that cache.', 'soapbox-for-blygger' ), 467 467 ), 468 468 'templated' => array( 469 469 __( 'Templated', 'soapbox-for-blygger' ), 470 __( 'Blygger 0.4 draft (decision #51). Needs a reader that supports manifest-located surfaces; most don\'t yet. The manifest says where everything else is, and the documents are served through the REST API. Managed hosts often cache paths ending in .json and .xml for weeks, which would keep serving an item after you withdrew it; this layout avoids those paths.', 'soapbox-for-blygger' ),470 __( 'Blygger 0.4\'s manifest-located surface: the manifest says where everything else is, and the documents are served through the REST API. Readers built to 0.4 must follow it, and the reference client does; a reader built only to 0.3 finds the manifest and then gets 404s. Managed hosts often cache paths ending in .json and .xml for weeks, which would keep serving an item after you withdrew it; this layout avoids those paths.', 'soapbox-for-blygger' ), 471 471 ), 472 472 ); … … 554 554 esc_html__( 'Delete all Soapbox for Blygger data when the plugin is deleted', 'soapbox-for-blygger' ) 555 555 ); 556 $note( __( ' Kept off while Soapbox Blyg, this plugin\'s earlier name, is still installed: the two share one record of what has been published, and deleting Soapbox Blyg with this on would delete it. Delete Soapbox Blyg from the Plugins screen first.', 'soapbox-for-blygger' ) );556 $note( __( 'Switched off while Soapbox Blyg, this plugin\'s earlier name, is still installed: the two share one record of what has been published, and deleting Soapbox Blyg with this on would delete it. It does not come back on by itself: delete Soapbox Blyg from the Plugins screen, then tick this again if you want it.', 'soapbox-for-blygger' ) ); 557 557 break; 558 558 } … … 581 581 sprintf( 582 582 /* translators: 1: protocol version, 2: URL of the protocol specification */ 583 __( 'This plugin publishes under the <a href="%2$s">Blygger protocol</a>, version %1$s , which is a draft: its wire format may change before 1.0, and this plugin will follow it. What does not change is the promise you make by publishing. Every address the blyg serves is meant to keep answering, and a pinned version is served forever. Soapbox for Blygger is an independent implementation and is not affiliated with the protocol\'s authors.', 'soapbox-for-blygger' ),583 __( 'This plugin publishes under the <a href="%2$s">Blygger protocol</a>, version %1$s. Like every version before 1.0 it is a draft: its wire format may change, and this plugin will follow it. What does not change is the promise you make by publishing. Every address the blyg serves is meant to keep answering, and a pinned version is served forever. Soapbox for Blygger is an independent implementation and is not affiliated with the protocol\'s authors.', 'soapbox-for-blygger' ), 584 584 esc_html( \SoapboxBlyg\Surface\Documents::PROTOCOL ), 585 esc_url( 'https://blygger.org/spec/ 0.3/' )585 esc_url( 'https://blygger.org/spec/' . \SoapboxBlyg\Surface\Documents::PROTOCOL . '/' ) 586 586 ), 587 587 array( 'a' => array( 'href' => true ) ) -
soapbox-for-blygger/trunk/src/Admin/ToolsPage.php
r3737840 r3754860 28 28 29 29 const PAGE = 'soapbox-blyg-tools'; 30 31 /** 32 * The user meta that records which schema problem a person has dismissed. 33 */ 34 const DISMISSED_META = 'soapbox_blyg_dismissed_problem'; 30 35 31 36 /** … … 110 115 $stamp = Schema::problem_key(); 111 116 if ( '' !== $problem && isset( $_GET['soapbox_blyg_dismiss'] ) && check_admin_referer( 'soapbox_blyg_dismiss' ) ) { 112 update_user_meta( get_current_user_id(), 'soapbox_blyg_dismissed_problem', $stamp );113 } 114 if ( '' !== $problem && ( $ours || get_user_meta( get_current_user_id(), 'soapbox_blyg_dismissed_problem', true ) !== $stamp ) ) {117 update_user_meta( get_current_user_id(), self::DISMISSED_META, $stamp ); 118 } 119 if ( '' !== $problem && ( $ours || get_user_meta( get_current_user_id(), self::DISMISSED_META, true ) !== $stamp ) ) { 115 120 echo '<div class="notice notice-error"><p>'; 116 121 echo esc_html( … … 391 396 /* translators: %s: the address of one of this site's items, as a link. Another publication's item is a fork of it. */ 392 397 'fork' => __( 'Forked from %s', 'soapbox-for-blygger' ), 398 /* translators: %s: the address of one of this site's items, as a link. Another publication's item has machine-generated text that drew on it. */ 399 'source' => __( 'Drew on %s', 'soapbox-for-blygger' ), 393 400 ); 394 401 ?> -
soapbox-for-blygger/trunk/src/Mentions/Verifier.php
r3737840 r3754860 456 456 $fetched_from = self::address( $document_url ); 457 457 if ( $speaker . 'items/' . $id . '.json' !== $fetched_from ) { 458 // Not at the fixed address, so the origin may publish its items by template ( §16.6e).458 // Not at the fixed address, so the origin may publish its items by template (spec §6.1, §15.4). 459 459 // Its manifest says where, and is the third and last document fetched: the page, the 460 460 // item document, and this. It is asked for at the claimed origin and nowhere else, so … … 477 477 $template = isset( $manifest['body'] ) && self::is_plain( $manifest['url'] ) && self::address( $manifest['url'] ) === $speaker . 'blyg.json' ? json_decode( $manifest['body'], true ) : null; 478 478 $template = is_array( $template ) && isset( $template['item'] ) && is_string( $template['item'] ) ? $template['item'] : ''; 479 // {id} is the only expression a template may hold (URI Template level 1, spec § 16.6e).479 // {id} is the only expression a template may hold (URI Template level 1, spec §6.1). 480 480 $expanded = str_replace( '{id}', rawurlencode( $id ), $template ); 481 481 if ( false === strpos( $template, '{id}' ) || false !== strpbrk( $expanded, '{}' ) || self::address( $expanded ) !== $fetched_from ) { … … 535 535 /** 536 536 * How a document refers to one of our items, if it does (spec §15.4), in the protocol's order: 537 * a stub of it, a transclusion of it, or a fork of a pinned version of it. Only the three 538 * identity members of a reference are read; `cited` and `selector` are never consulted. 537 * a stub of it, a transclusion of it, a fork of a pinned version of it, or a generation source 538 * drawn from it. Only the identity members of a reference are read; `cited` and `selector` 539 * are never consulted. 539 540 * 540 541 * @param array $document The source's item document. 541 542 * @param string $our_url This origin's URL: its identity. 542 543 * @param string $target_id Our item's id. 543 * @return string|null stub, transclusion, fork or null.544 * @return string|null stub, transclusion, fork, source or null. 544 545 */ 545 546 private function relation( array $document, string $our_url, string $target_id ) { … … 570 571 if ( $row && (int) $row['pinned'] ) { 571 572 return 'fork'; 573 } 574 } 575 // A generation source (spec 0.4 §5.7): one of our items that machine-generated text in the 576 // document drew on. Each span of `generated` lists its sources as references; one without 577 // an origin is the sender's own item. Nothing is promised of the version, so no pin check. 578 if ( isset( $document['generated'] ) && is_array( $document['generated'] ) ) { 579 foreach ( $document['generated'] as $span ) { 580 if ( ! is_array( $span ) || ! isset( $span['sources'] ) || ! is_array( $span['sources'] ) ) { 581 continue; 582 } 583 foreach ( $span['sources'] as $entry ) { 584 if ( $names( $entry ) ) { 585 return 'source'; 586 } 587 } 572 588 } 573 589 } -
soapbox-for-blygger/trunk/src/Plugin.php
r3737840 r3754860 36 36 37 37 /** 38 * The WP-CLI command: `wp blyg`. 39 */ 40 const CLI_COMMAND = 'blyg'; 41 42 /** 38 43 * The one instance. 39 44 * … … 203 208 204 209 if ( defined( 'WP_CLI' ) && WP_CLI ) { 205 \WP_CLI::add_command( 'blyg', Cli\Command::class );210 \WP_CLI::add_command( self::CLI_COMMAND, Cli\Command::class ); 206 211 } 207 212 } … … 239 244 * this plugin is serving from: every id and every address the site has published. Nothing in 240 245 * this plugin runs at that moment, so the setting is switched off beforehand, here, and the 241 * settings screen will not switch it on again until the earlier plugin has gone. 246 * settings screen will not switch it on again until the earlier plugin has gone. Nor does 247 * anything else: the owner ticks it again. 242 248 * 243 249 * The file is looked for only when the setting is on, so an ordinary request reads nothing extra. … … 263 269 return; 264 270 } 265 echo '<div class="notice notice-info"><p>' . esc_html__( 'Soapbox Blyg, the earlier name of Soapbox for Blygger, is still installed. It can be deleted: this plugin has taken over the same blyg, at the same addresses. Until it has gone, "Delete all data when the plugin is deleted" is kept switched off, because deleting Soapbox Blyg with that setting on would delete the record of everything this site has published.', 'soapbox-for-blygger' ) . '</p></div>';271 echo '<div class="notice notice-info"><p>' . esc_html__( 'Soapbox Blyg, the earlier name of Soapbox for Blygger, is still installed. It can be deleted: this plugin has taken over the same blyg, at the same addresses. Until it has gone, "Delete all data when the plugin is deleted" stays switched off, because deleting Soapbox Blyg with that setting on would delete the record of everything this site has published. It does not come back on by itself: after deleting Soapbox Blyg, tick it again if you want it.', 'soapbox-for-blygger' ) . '</p></div>'; 266 272 } 267 273 -
soapbox-for-blygger/trunk/src/Surface/Documents.php
r3737840 r3754860 28 28 29 29 /** 30 * The protocol version these documents are written to (spec §3.1). 31 */ 32 const PROTOCOL = '0.3'; 30 * The protocol version these documents are written to (spec §3.1). One value for every 31 * document in both layouts, pinned versions included: a pin promises its content, which 32 * content_hash covers, not its bytes (§8). 33 */ 34 const PROTOCOL = '0.4'; 33 35 34 36 /** -
soapbox-for-blygger/trunk/src/Surface/Locations.php
r3737840 r3754860 20 20 * The manifest is always at {origin}blyg.json: that filename is what lets a reader handed a bare 21 21 * origin find the blyg, and it is what makes the origin, and so the blyg's identity, a stable 22 * path of the site's own choosing (spec § 12.2, §16.6e). Everything past the manifest is located22 * path of the site's own choosing (spec §4, §12.2). Everything past the manifest is located 23 23 * by the manifest: 24 24 * … … 177 177 * The item a URL names, within one origin: by its page, in any spelling the item has ever had, 178 178 * or by its item document URL in the origin's current layout. This is the check a Webmention's 179 * target has to pass (spec §15.3 , §16.6e: receivers check targets against their own templates).179 * target has to pass (spec §15.3: receivers check targets against their own templates). 180 180 * 181 181 * @param Origin $origin The origin. -
soapbox-for-blygger/trunk/src/Surface/RestDocuments.php
r3737840 r3754860 18 18 /** 19 19 * Serves the feed, the archive index, item documents and pinned versions of a templated origin 20 * from REST routes. The manifest names these URLs and readers follow it (spec § 16.6e), so the20 * from REST routes. The manifest names these URLs and readers follow it (spec §6.1), so the 21 21 * documents can sit where WordPress routes natively, away from the .json and .xml paths that 22 22 * managed hosts treat as static files and cache at the edge. -
soapbox-for-blygger/trunk/src/Surface/Router.php
r3737840 r3754860 25 25 * 26 26 * The REST API is not used for the manifest: the protocol fixes that one filename at the origin 27 * (spec §4, § 16.6e), and {origin}blyg.json is what makes the origin's identity a path the site27 * (spec §4, §6.1), and {origin}blyg.json is what makes the origin's identity a path the site 28 28 * owns. add_feed() is not used either: it serves /feed/{name}/, and the protocol's default feed 29 29 * path is {origin}feed.xml.
Note:
See TracChangeset
for help on using the changeset viewer.