Class: Jekyll::L10n::PoPathBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/jekyll-l10n/po_file/path_builder.rb

Overview

Constructs file paths for PO files.

PoPathBuilder creates proper file paths for both compendium (locale-level) and page-specific PO files. Compendium files are at the locale level (locales_dir/locale.po), while page-specific files are nested (locales_dir/locale/page_path.po).

Key responsibilities:

  • Build paths for compendium PO files

  • Build paths for page-specific PO files

  • Handle file path normalization and validation

  • Prevent path traversal attacks

Examples:

compendium = PoPathBuilder.build('_site', '_locales', 'es', nil)
# Returns '_site/_locales/es.po'
page_specific = PoPathBuilder.build('_site', '_locales', 'es', 'docs/index.html')
# Returns '_site/_locales/es/docs/index.html.po'

Class Method Summary collapse

Class Method Details

.build(source, locales_dir, locale, page_path) ⇒ String

Build a PO file path.

For compendium (page_path nil): source/locales_dir/locale.po For page-specific: source/locales_dir/locale/page_path.po

Validates that page_path doesn’t escape the base directory using path traversal techniques (e.g., ../../../etc/passwd).

Parameters:

  • source (String)

    Site source directory

  • locales_dir (String)

    Locales directory name (e.g., ‘_locales’)

  • locale (String)

    Locale code (e.g., ‘es’, ‘fr’)

  • page_path (String, nil)

    Page path for page-specific file, nil for compendium

Returns:

  • (String)

    Full path to PO file

Raises:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/jekyll-l10n/po_file/path_builder.rb', line 38

def self.build(source, locales_dir, locale, page_path)
  if page_path.nil?
    File.join(source, locales_dir, "#{locale}.po")
  else
    # Build the normal path
    normal_path = File.join(source, locales_dir, locale, "#{page_path}.po")

    # Validate against path traversal using expanded paths
    base_path = File.expand_path(File.join(source, locales_dir))
    expanded_path = File.expand_path(normal_path)

    # Security: Validate path stays within base directory
    valid_path = expanded_path.start_with?(base_path + File::SEPARATOR) ||
                 expanded_path == base_path
    unless valid_path
      raise Jekyll::L10n::Errors::PoFileError,
            "Path traversal attempt detected in page_path: #{page_path}"
    end

    normal_path
  end
end