Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions citecue.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: CiteCue AI Auto-Fix
* Plugin URI: https://github.com/citecue/wordpress-plugin
* Description: Serves CiteCue-optimized versions of your pages to AI bots and crawlers, publishes your llms.txt, and lets CiteCue push brand-building draft content into WordPress.
* Version: 1.0.1
* Version: 1.0.2
* Requires at least: 5.8
* Requires PHP: 7.4
* Author: CiteCue
Expand Down Expand Up @@ -56,7 +56,7 @@ static function () {
return;
}

define( 'CITECUE_VERSION', '1.0.1' );
define( 'CITECUE_VERSION', '1.0.2' );
define( 'CITECUE_PLUGIN_FILE', __FILE__ );
define( 'CITECUE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );

Expand Down
4 changes: 3 additions & 1 deletion includes/class-citecue-llms-txt.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ private function is_llms_txt_request() {
return false;
}

$path = (string) wp_parse_url( wp_unslash( $_SERVER['REQUEST_URI'] ), PHP_URL_PATH );
// esc_url_raw() rather than sanitize_text_field(), which strips
// percent-encoded sequences and would corrupt the path being matched.
$path = (string) wp_parse_url( esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ), PHP_URL_PATH );

$home_path = (string) wp_parse_url( home_url( '/' ), PHP_URL_PATH );
$target = untrailingslashit( $home_path ) . '/llms.txt';
Expand Down
9 changes: 6 additions & 3 deletions includes/class-citecue-plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,16 @@ private function __construct() {
}

/**
* Init: translations + cron self-heal.
* Init: cron self-heal.
*
* There is deliberately no load_plugin_textdomain() call. Since WordPress
* 4.6 a plugin hosted on WordPress.org has its translations loaded for it,
* keyed by the slug — which is exactly what the text domain is now. The
* call was pointing at a languages/ directory this plugin does not ship.
*
* @return void
*/
public function on_init() {
load_plugin_textdomain( 'citecue-ai-auto-fix', false, dirname( plugin_basename( CITECUE_PLUGIN_FILE ) ) . '/languages' );

if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
wp_schedule_event( time() + MINUTE_IN_SECONDS, 'daily', self::CRON_HOOK );
}
Expand Down
5 changes: 4 additions & 1 deletion includes/class-citecue-proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,10 @@ private function current_url() {
}
$scheme = is_ssl() ? 'https' : 'http';
$host = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) );
$uri = wp_unslash( $_SERVER['REQUEST_URI'] );
// esc_url_raw(), not sanitize_text_field(): the latter deletes every
// percent-encoded sequence it finds, so /caf%C3%A9/ would reach CiteCue
// as /caf/ and be cached under the wrong key.
$uri = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) );
return esc_url_raw( $scheme . '://' . $host . $uri );
}

Expand Down
6 changes: 5 additions & 1 deletion readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Tags: ai, llms.txt, gptbot, ai-seo, woocommerce
Requires at least: 5.8
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.0.1
Stable tag: 1.0.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Expand Down Expand Up @@ -100,6 +100,10 @@ The plugin folder is now citecue-ai-auto-fix. If you installed 1.0.0 by uploadin

== Changelog ==

= 1.0.2 =
* Translations no longer depend on the plugin loading them by hand; WordPress.org supplies them for the plugin slug.
* The requested URL is sanitized on the way to CiteCue in a way that preserves percent-encoding, so pages with accented or non-Latin characters in the address are served and cached under the address they actually have.

= 1.0.1 =
* First release in the WordPress.org plugin directory.
* An install that has not been connected to CiteCue now makes no outbound requests of any kind: the daily crawler-registry refresh waits for a connection.
Expand Down
21 changes: 21 additions & 0 deletions tests/cases/test-proxy-delivery.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,27 @@ public function test_delivery_request_is_addressed_correctly() {
$this->assertSame( 'wordpress', $request['args']['headers']['X-Citecue-Channel'] );
}

/**
* The requested URL reaches CiteCue with its percent-encoding intact.
*
* This is a standing trap rather than a hypothetical: REQUEST_URI has to
* be sanitized to satisfy Plugin Check, and the reflex choice —
* sanitize_text_field() — deletes every %xx sequence it finds. Under it
* this URL would arrive as /caf/, which is a different page, cached under
* a key CiteCue never answers for.
*
* @return void
*/
public function test_a_percent_encoded_url_is_not_mangled_on_the_way_out() {
$encoded = $this->fake_crawler_request( '/caf%C3%A9/' );
$this->http->queue( 'page', 200, '<html>optimized</html>' );

$this->proxy()->decide();

$this->assertStringContainsString( '%C3%A9', rawurldecode( $this->http->last( 'page' )['url'] ) );
$this->assertStringContainsString( 'caf%C3%A9', $encoded );
}

/**
* A second hit revalidates with the stored ETag instead of re-downloading.
*
Expand Down
Loading