Class: Yast::PunycodeClass

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

Constant Summary collapse

NOT_CACHED_REGEXP =

string, matching this regexp, is not cached

/^[0123456789.]*$/.freeze

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.


178
179
180
181
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
# File 'library/types/src/modules/Punycode.rb', line 178

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.


88
89
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
# File 'library/types/src/modules/Punycode.rb', line 88

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.

Examples:

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

269
270
271
272
273
274
# File 'library/types/src/modules/Punycode.rb', line 269

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.


241
242
243
244
# File 'library/types/src/modules/Punycode.rb', line 241

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."]

287
288
289
290
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
# File 'library/types/src/modules/Punycode.rb', line 287

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.

Examples:

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

254
255
256
257
258
259
# File 'library/types/src/modules/Punycode.rb', line 254

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.


231
232
233
234
# File 'library/types/src/modules/Punycode.rb', line 231

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.


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

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.


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

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).

See Also:

  • #SetMaximumCacheSize()

65
66
67
# File 'library/types/src/modules/Punycode.rb', line 65

def GetMaximumCacheSize
  @maximum_cache_size
end

#GetTmpDirectoryObject

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


169
170
171
172
173
# File 'library/types/src/modules/Punycode.rb', line 169

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

  @tmp_dir
end

#mainObject


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

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).

See Also:

  • #GetMaximumCacheSize()

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

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