Class: Yast::PunycodeClass

Inherits:
Module
  • Object
show all
Defined in:
library/types/src/modules/Punycode.rb

Constant Summary

NOT_CACHED_REGEXP =

string, matching this regexp, is not cached

/^[0123456789.]*$/

Instance Method Summary collapse

Instance Method Details

#ConvertBackAndForth(strings_in, to_punycode) ⇒ Object

Function takes the list of strings and returns them in the converted format. Unicode to Punycode or Punycode to Unicode (param to_punycode). It uses a cache of already-converted strings.



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'library/types/src/modules/Punycode.rb', line 182

def ConvertBackAndForth(strings_in, to_punycode)
  # Some (or maybe all) strings needn't be cached
  not_cached = []

  # Check the cache for already entered strings
  test_cached = strings_in.each_with_object({}) do |string_in, all|
    # Numbers, IPs and empty strings are not converted
    string_out =
      if NOT_CACHED_REGEXP.match?(string_in)
        string_in
      elsif to_punycode
        GetEncodedCachedString(string_in)
      else
        GetDecodedCachedString(string_in)
      end

    not_cached << string_in if string_out.nil?
    all[string_in] = string_out
  end

  converted_not_cached = []

  # There is something not cached, converting them at once
  if !not_cached.empty?
    meth = to_punycode ? :to_ascii : :to_unicode
    converted_not_cached = not_cached.map { |v| SimpleIDN.public_send(meth, v) }
  end

  # Listing through the given list and adjusting the return list
  found_index = -1
  strings_in.each_with_object([]) do |string_in, all|
    # Already cached string
    if test_cached[string_in]
      all << test_cached[string_in]
    else # Recently converted strings
      found_index += 1
      all << converted_not_cached[found_index] || ""

      # Adding converted strings to cache
      if to_punycode
        CreateNewCacheRecord(string_in, converted_not_cached[found_index] || "")
      else
        CreateNewCacheRecord(converted_not_cached[found_index] || "", string_in)
      end
    end
  end
end

#CreateNewCacheRecord(decoded, encoded) ⇒ Object

Adds new cache records for encoded and decoded strings.

Parameters:



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'library/types/src/modules/Punycode.rb', line 90

def CreateNewCacheRecord(decoded, encoded)
  # Erroneous cache record
  return if decoded.nil? || encoded.nil?

  # Already cached
  return if Builtins.contains(@cache_decoded, decoded)

  decoded_size = Builtins.size(decoded)
  encoded_size = Builtins.size(encoded)

  # Do not store this record if the cache would exceed maximum
  if Ops.greater_than(
    Ops.add(Ops.add(@current_cache_size, decoded_size), encoded_size),
    @maximum_cache_size
  )
    return
  end

  @current_cache_size = Ops.add(
    Ops.add(@current_cache_size, decoded_size),
    encoded_size
  )
  Ops.set(@cache_decoded, @current_cache_index, decoded)
  Ops.set(@cache_encoded, @current_cache_index, encoded)
  @current_cache_index = Ops.add(@current_cache_index, 1)

  nil
end

#DecodeDomainName(encoded_domain_name) ⇒ String

Decodes the domain name (relative or FQDN) from the Punycode.

DecodeDomainName(“xn–ala-qma83eb.xn–jlinka-3mb.go.home”) -> “žížala.jůlinka.go.home”

Parameters:

  • encoded_domain_name (String)

Returns:

  • (String)

    decoded domain_name



273
274
275
276
277
278
# File 'library/types/src/modules/Punycode.rb', line 273

def DecodeDomainName(encoded_domain_name)
  Builtins.mergestring(
    DecodePunycodes(Builtins.splitstring(encoded_domain_name, ".")),
    "."
  )
end

#DecodePunycodes(punycode_strings) ⇒ Array<String>

Converts list of Punycode strings into their UTF-8 representation.

Parameters:

  • punycode_strings (Array<String>)

Returns:

  • (Array<String>)

    decoded_strings



245
246
247
248
# File 'library/types/src/modules/Punycode.rb', line 245

def DecodePunycodes(punycode_strings)
  punycode_strings = deep_copy(punycode_strings)
  ConvertBackAndForth(punycode_strings, false)
end

#DocodeDomainNames(encoded_domain_names) ⇒ Array<String>

Decodes the list of domain names to their Unicode representation. This function is similar to DecodePunycodes but it works with every string as a domain name (that means every domain name is parsed by dots and separately evaluated).

Examples:

DocodeDomainNames(["mx1.example.org", "xp3.example.org.", "xn--ala-qma83eb.org.example."])
-> ["mx1.example.org", "xp3.example.org.", "žížala.org.example."]

Parameters:

  • encoded_domain_names (Array<String>)

Returns:

  • (Array<String>)

    decoded_domain_names



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'library/types/src/modules/Punycode.rb', line 291

def DocodeDomainNames(encoded_domain_names)
  encoded_domain_names = deep_copy(encoded_domain_names)
  decoded_domain_names = []
  strings_to_decode = []

  # $[0 : [0, 2], 1 : [3, 5]]
  backward_map_of_conversion = {}

  current_domain_index = -1
  current_domain_item = 0

  # parsing all domain names one by one
  Builtins.foreach(encoded_domain_names) do |one_domain_name|
    current_domain_index = Ops.add(current_domain_index, 1)
    start = current_domain_item
    # parsing the domain name by dots
    Builtins.foreach(Builtins.splitstring(one_domain_name, ".")) do |domain_item|
      Ops.set(strings_to_decode, current_domain_item, domain_item)
      current_domain_item = Ops.add(current_domain_item, 1)
    end
    # creating backward index
    Ops.set(
      backward_map_of_conversion,
      current_domain_index,
      [start, Ops.subtract(current_domain_item, 1)]
    )
  end

  # Transformating strings to the decoded format
  strings_to_decode = DecodePunycodes(strings_to_decode)

  current_domain_index = -1
  Builtins.foreach(encoded_domain_names) do |one_encoded|
    current_domain_index = Ops.add(current_domain_index, 1)
    # Where the current string starts and ends
    current = Ops.get(backward_map_of_conversion, [current_domain_index, 0])
    end_ = Ops.get(backward_map_of_conversion, [current_domain_index, 1])
    # error?
    if current.nil? || end_.nil?
      Builtins.y2error(
        "Cannot find start/end for %1 in %2",
        one_encoded,
        Ops.get(backward_map_of_conversion, current_domain_index)
      )
      Ops.set(decoded_domain_names, current_domain_index, one_encoded)
    else
      # create a list of items of the current domain (translated)
      decoded_domain = []
      while Ops.less_or_equal(current, end_)
        decoded_domain = Builtins.add(
          decoded_domain,
          Ops.get(strings_to_decode, current, "")
        )
        current = Ops.add(current, 1)
      end
      # create a domain name from these strings
      Ops.set(
        decoded_domain_names,
        current_domain_index,
        Builtins.mergestring(decoded_domain, ".")
      )
    end
  end

  deep_copy(decoded_domain_names)
end

#EncodeDomainName(decoded_domain_name) ⇒ String

Encodes the domain name (relative or FQDN) to the Punycode.

EncodeDomainName(“žížala.jůlinka.go.home”) -> “xn–ala-qma83eb.xn–jlinka-3mb.go.home”

Parameters:

  • string

    decoded domain_name

Returns:

  • (String)

    encoded domain_name



258
259
260
261
262
263
# File 'library/types/src/modules/Punycode.rb', line 258

def EncodeDomainName(decoded_domain_name)
  Builtins.mergestring(
    EncodePunycodes(Builtins.splitstring(decoded_domain_name, ".")),
    "."
  )
end

#EncodePunycodes(punycode_strings) ⇒ Array<String>

Converts list of UTF-8 strings into their Punycode ASCII repserentation.

Parameters:

  • punycode_strings (Array<String>)

Returns:

  • (Array<String>)

    encoded_strings



235
236
237
238
# File 'library/types/src/modules/Punycode.rb', line 235

def EncodePunycodes(punycode_strings)
  punycode_strings = deep_copy(punycode_strings)
  ConvertBackAndForth(punycode_strings, true)
end

#GetDecodedCachedString(encoded_string) ⇒ String

Returns string encoded in Punycode if it has been already cached. Returns nil if not found.

Parameters:

  • encoded_string (String)

    (Punycode)

Returns:

  • (String)

    decoded_string (Unicode)



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'library/types/src/modules/Punycode.rb', line 149

def GetDecodedCachedString(encoded_string)
  ret = nil

  # numbers and empty strings are not converted
  return encoded_string if NOT_CACHED_REGEXP.match?(encoded_string)

  counter = -1
  # searching through encoded strings to find the index
  Builtins.foreach(@cache_encoded) do |cached_string|
    counter = Ops.add(counter, 1)
    if cached_string == encoded_string
      # returning decoded representation
      ret = Ops.get(@cache_decoded, counter)
      raise Break
    end
  end

  ret
end

#GetEncodedCachedString(decoded_string) ⇒ String

Returns string encoded in Punycode if it has been already cached. Returns nil if not found.

Parameters:

  • decoded_string (String)

    (Unicode)

Returns:

  • (String)

    encoded_string (Punycode)



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'library/types/src/modules/Punycode.rb', line 124

def GetEncodedCachedString(decoded_string)
  ret = nil

  # numbers and empty strings are not converted
  return decoded_string if NOT_CACHED_REGEXP.match?(decoded_string)

  counter = -1
  # searching through decoded strings to find the index
  Builtins.foreach(@cache_decoded) do |cached_string|
    counter = Ops.add(counter, 1)
    if cached_string == decoded_string
      # returning encoded representation
      ret = Ops.get(@cache_encoded, counter)
      raise Break
    end
  end

  ret
end

#GetMaximumCacheSizeFixnum

Returns the maximum cache size (sum of already converted strings).

Returns:

  • (Fixnum)

    maximum_cache_size

See Also:

  • #SetMaximumCacheSize()


67
68
69
# File 'library/types/src/modules/Punycode.rb', line 67

def GetMaximumCacheSize
  @maximum_cache_size
end

#GetTmpDirectoryObject

Returns the current temporary directory. Lazy loading for the initialization is used.



171
172
173
174
175
176
177
# File 'library/types/src/modules/Punycode.rb', line 171

def GetTmpDirectory
  if @tmp_dir.nil?
    @tmp_dir = Convert.to_string(SCR.Read(path(".target.tmpdir")))
  end

  @tmp_dir
end

#mainObject



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'library/types/src/modules/Punycode.rb', line 40

def main
  textdomain "base"

  @tmp_dir = nil

  #
  # Encoded string in cache has the same index
  # as its Decoded format in the second list.
  #

  # list of encoded strings to be cached (Punycode or Unicode)
  @cache_encoded = []
  # list of decoded strings to be cached (Unicode or Punycode)
  @cache_decoded = []

  @current_cache_index = 0

  # cached amount of data should be controled
  @current_cache_size = 0
  @maximum_cache_size = 32_768
end

#SetMaximumCacheSize(new_max_size) ⇒ Object

Offers to set the maximum cache size (sum of already converted strings).

Parameters:

  • new_max_size (Fixnum)

See Also:

  • #GetMaximumCacheSize()


76
77
78
79
80
81
82
83
84
# File 'library/types/src/modules/Punycode.rb', line 76

def SetMaximumCacheSize(new_max_size)
  if !new_max_size.nil?
    @maximum_cache_size = new_max_size
  else
    Builtins.y2error("Cannot set MaximumCacheSize to nil!")
  end

  nil
end