| @@ -50,10 +50,16 @@ | ||
| 50 | 50 | * @param string $filename Filename. |
| 51 | 51 | * @return string |
| 52 | 52 | */ |
| 53 | 53 | public function path( string $filename ): string { |
| 54 | - $filename = str_replace( array( '../', '..\\', "\0" ), '', ltrim( $filename, '/' ) ); | |
| 54 | + $filename = str_replace( "\0", '', ltrim( $filename, '/' ) ); | |
| 55 | 55 | |
| 56 | + // Iteratively strip '..' so a removal can never re-form a traversal | |
| 57 | + // sequence (a single-pass '../' replace turns '....//' into '../'). | |
| 58 | + while ( false !== strpos( $filename, '..' ) ) { | |
| 59 | + $filename = str_replace( '..', '', $filename ); | |
| 60 | + } | |
| 61 | + | |
| 56 | 62 | return trailingslashit( EASYFONTS_CACHE_DIR ) . $filename; |
| 57 | 63 | } |
| 58 | 64 | |
| 59 | 65 | /** |
| @@ -71,8 +77,31 @@ | ||
| 71 | 77 | public function url( string $filename ): string { |
| 72 | 78 | $url = trailingslashit( EASYFONTS_CACHE_URL ) . ltrim( $filename, '/' ); |
| 73 | 79 | |
| 74 | 80 | return self::cdn_rewrite( $url ); |
| 81 | + } | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Public URL of a hosted FONT, versioned by the file itself. | |
| 85 | + * | |
| 86 | + * (2.0.4) Font URLs used to carry the site-wide cache-buster, which every | |
| 87 | + * settings save bumps. The consolidated stylesheet is written once and | |
| 88 | + * reused, so its @font-face URLs kept the old buster while preloads took | |
| 89 | + * the new one: two URLs for one file — the preload went unused ("preloaded | |
| 90 | + * but not used") and the font downloaded twice. A file's own modification | |
| 91 | + * time changes only when the file itself is (re)written, so every place | |
| 92 | + * that links a font — stylesheet, preload, localised theme CSS — computes | |
| 93 | + * the same URL, and a settings save no longer makes every returning visitor | |
| 94 | + * download every font again. Fonts are served immutable for a year, so the | |
| 95 | + * version is still needed for when a file really is re-downloaded. | |
| 96 | + * | |
| 97 | + * @param string $filename Cache-relative font filename. | |
| 98 | + * @return string | |
| 99 | + */ | |
| 100 | + public function font_url( string $filename ): string { | |
| 101 | + $mtime = @filemtime( $this->path( $filename ) ); // phpcs:ignore WordPress.PHP.NoSilencedErrors | |
| 102 | + | |
| 103 | + return add_query_arg( 'ver', $mtime ? (int) $mtime : \EasyFonts\Settings::buster(), $this->url( $filename ) ); | |
| 75 | 104 | } |
| 76 | 105 | |
| 77 | 106 | /** |
| 78 | 107 | * Rewrite a same-origin asset URL onto the configured CDN origin. |