Projects
openEuler:24.03:SP1:Everything:64G
ruby
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
_service:tar_scm:ruby.spec
Changed
@@ -33,7 +33,7 @@ Name: ruby Version: %{ruby_version} -Release: 143 +Release: 147 Summary: Object-oriented scripting language interpreter License: (Ruby or BSD) and Public Domain and MIT and CC0 and zlib and UCD URL: https://www.ruby-lang.org/en/ @@ -99,6 +99,10 @@ Patch6023: backport-0005-CVE-2024-35221.patch Patch6024: upgrade-lib-rexml-to-3.3.1.patch Patch6025: backport-CVE-2024-41946.patch +Patch6026: backport-CVE-2024-39908-CVE-2024-41123-upgrade-lib-rexml-to-3.3.3.patch +Patch6027: backport-CVE-2024-43398-upgrade-lib-rexml-to-3.3.6.patch +Patch6028: backport-CVE-2024-47220.patch +Patch6029: backport-CVE-2024-49761.patch Provides: %{name}-libs = %{version}-%{release} Obsoletes: %{name}-libs < %{version}-%{release} @@ -188,7 +192,7 @@ %package -n rubygem-rdoc Summary: Generate HTML and command-line documentation for Ruby projects Version: %{rdoc_version} -License: GPLv2 and Ruby and MIT and OFL +License: GPLv2 and Ruby and MIT and OFL-1.1-RFN Requires: ruby(release) ruby(rubygems) >= %{rubygems_version} ruby(irb) = %{ruby_version} rubygem(io-console) >= %{io_console_version} rubygem(json) >= %{json_version} Provides: rdoc = %{version}-%{release} ri = %{version}-%{release} rubygem(rdoc) = %{version}-%{release} BuildArch: noarch @@ -884,6 +888,18 @@ %{gem_dir}/specifications/matrix-%{matrix_version}.gemspec %changelog +* Tue Oct 29 2024 shixuantong <shixuantong1@huawei.com> - 3.2.2-147 +- fix CVE-2024-49761 + +* Tue Oct 08 2024 shixuantong <shixuantong1@huawei.com> - 3.2.2-146 +- fix CVE-2024-47220 + +* Thu Aug 29 2024 shixuantong <shixuantong1@huawei.com> - 3.2.2-145 +- upgrade rexml to fix CVE-2024-39908 CVE-2024-41123 CVE-2024-43398 + +* Wed Aug 14 2024 wangjiang <wangjiang37@h-partners.com> - 3.2.2-144 +- License compliance rectification + * Thu Aug 08 2024 zhangxianting <zhangxianting@uniontech.com> - 3.2.2-143 - fix CVE-2024-41946
View file
_service:tar_scm:backport-CVE-2024-39908-CVE-2024-41123-upgrade-lib-rexml-to-3.3.3.patch
Added
@@ -0,0 +1,372 @@ +From e4a067e11235a2ec7a00616d41350485e384ec05 Mon Sep 17 00:00:00 2001 +From: Sutou Kouhei <kou@clear-code.com> +Date: Thu, 1 Aug 2024 11:51:33 +0900 +Subject: PATCH Add 3.3.3 entry + +--- + .../lib/rexml/formatters/pretty.rb | 2 +- + .../lib/rexml/parsers/baseparser.rb | 67 ++++++++++++++----- + .../lib/rexml/parsers/sax2parser.rb | 21 +----- + .../lib/rexml/parsers/streamparser.rb | 4 +- + .bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb | 2 +- + .bundle/gems/rexml-3.2.5/lib/rexml/source.rb | 22 ++++-- + .bundle/gems/rexml-3.2.5/lib/rexml/text.rb | 48 +++++++++---- + 7 files changed, 105 insertions(+), 61 deletions(-) + +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb +index a1198b7..a838d83 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/formatters/pretty.rb +@@ -111,7 +111,7 @@ module REXML + # itself, then we don't need a carriage return... which makes this + # logic more complex. + node.children.each { |child| +- next if child == node.children-1 and child.instance_of?(Text) ++ next if child.instance_of?(Text) + unless child == node.children0 or child.instance_of?(Text) or + (child == node.children1 and !node.children0.writethis) + output << "\n" +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +index 617a3d5..44dc658 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +@@ -124,11 +124,10 @@ module REXML + } + + module Private +- INSTRUCTION_END = /#{NAME}(\s+.*?)?\?>/um + TAG_PATTERN = /((?>#{QNAME_STR}))\s*/um + CLOSE_PATTERN = /(#{QNAME_STR})\s*>/um + ATTLISTDECL_END = /\s+#{NAME}(?:#{ATTDEF})*\s*>/um +- NAME_PATTERN = /\s*#{NAME}/um ++ NAME_PATTERN = /#{NAME}/um + GEDECL_PATTERN = "\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>" + PEDECL_PATTERN = "\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>" + ENTITYDECL_PATTERN = /(?:#{GEDECL_PATTERN})|(?:#{PEDECL_PATTERN})/um +@@ -159,6 +158,7 @@ module REXML + def stream=( source ) + @source = SourceFactory.create_from( source ) + @closed = nil ++ @have_root = false + @document_status = nil + @tags = + @stack = +@@ -241,7 +241,7 @@ module REXML + if @document_status == nil + start_position = @source.position + if @source.match("<?", true) +- return process_instruction(start_position) ++ return process_instruction + elsif @source.match("<!", true) + if @source.match("--", true) + md = @source.match(/(.*?)-->/um, true) +@@ -311,7 +311,11 @@ module REXML + raise REXML::ParseException.new( "Bad ELEMENT declaration!", @source ) if md.nil? + return :elementdecl, "<!ELEMENT" + md1 + elsif @source.match("ENTITY", true) +- match = :entitydecl, *@source.match(Private::ENTITYDECL_PATTERN, true).captures.compact ++ match_data = @source.match(Private::ENTITYDECL_PATTERN, true) ++ unless match_data ++ raise REXML::ParseException.new("Malformed entity declaration", @source) ++ end ++ match = :entitydecl, *match_data.captures.compact + ref = false + if match1 == '%' + ref = true +@@ -343,7 +347,7 @@ module REXML + contents = md0 + + pairs = {} +- values = md0.scan( ATTDEF_RE ) ++ values = md0.strip.scan( ATTDEF_RE ) + values.each do |attdef| + unless attdef3 == "#IMPLIED" + attdef.compact! +@@ -437,7 +441,7 @@ module REXML + raise REXML::ParseException.new( "Declarations can only occur "+ + "in the doctype declaration.", @source) + elsif @source.match("?", true) +- return process_instruction(start_position) ++ return process_instruction + else + # Get the next tag + md = @source.match(Private::TAG_PATTERN, true) +@@ -462,8 +466,12 @@ module REXML + @closed = tag + @nsstack.shift + else ++ if @tags.empty? and @have_root ++ raise ParseException.new("Malformed XML: Extra tag at the end of the document (got '<#{tag}')", @source) ++ end + @tags.push( tag ) + end ++ @have_root = true + return :start_element, tag, attributes + end + else +@@ -471,6 +479,16 @@ module REXML + if text.chomp!("<") + @source.position -= "<".bytesize + end ++ if @tags.empty? ++ unless /\A\s*\z/.match?(text) ++ if @have_root ++ raise ParseException.new("Malformed XML: Extra content at the end of the document (got '#{text}')", @source) ++ else ++ raise ParseException.new("Malformed XML: Content at the start of the document (got '#{text}')", @source) ++ end ++ end ++ return pull_event if @have_root ++ end + return :text, text + end + rescue REXML::UndefinedNamespaceException +@@ -515,7 +533,11 @@ module REXML + + # Unescapes all possible entities + def unnormalize( string, entities=nil, filter=nil ) +- rv = string.gsub( Private::CARRIAGE_RETURN_NEWLINE_PATTERN, "\n" ) ++ if string.include?("\r") ++ rv = string.gsub( Private::CARRIAGE_RETURN_NEWLINE_PATTERN, "\n" ) ++ else ++ rv = string.dup ++ end + matches = rv.scan( REFERENCE_RE ) + return rv if matches.size == 0 + rv.gsub!( Private::CHARACTER_REFERENCES ) { +@@ -565,14 +587,14 @@ module REXML + def parse_name(base_error_message) + md = @source.match(Private::NAME_PATTERN, true) + unless md +- if @source.match(/\s*\S/um) ++ if @source.match(/\S/um) + message = "#{base_error_message}: invalid name" + else + message = "#{base_error_message}: name is missing" + end + raise REXML::ParseException.new(message, @source) + end +- md1 ++ md0 + end + + def parse_id(base_error_message, +@@ -641,15 +663,24 @@ module REXML + end + end + +- def process_instruction(start_position) +- match_data = @source.match(Private::INSTRUCTION_END, true) +- unless match_data +- message = "Invalid processing instruction node" +- @source.position = start_position +- raise REXML::ParseException.new(message, @source) ++ def process_instruction ++ name = parse_name("Malformed XML: Invalid processing instruction node") ++ if @source.match(/\s+/um, true) ++ match_data = @source.match(/(.*?)\?>/um, true) ++ unless match_data ++ raise ParseException.new("Malformed XML: Unclosed processing instruction", @source) ++ end ++ content = match_data1 ++ else ++ content = nil ++ unless @source.match("?>", true) ++ raise ParseException.new("Malformed XML: Unclosed processing instruction", @source) ++ end + end +- if @document_status.nil? and match_data1 == "xml" +- content = match_data2 ++ if name == "xml" ++ if @document_status ++ raise ParseException.new("Malformed XML: XML declaration is not at the start", @source) ++ end + version = VERSION.match(content) + version = version1 unless version.nil? + encoding = ENCODING.match(content) +@@ -664,7 +695,7 @@ module REXML + standalone = standalone1 unless standalone.nil? + return :xmldecl, version, encoding, standalone + end +- :processing_instruction, match_data1, match_data2 ++ :processing_instruction, name, content + end + + def parse_attributes(prefixes, curr_ns) +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb +index 01cb469..cec9d2f 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/sax2parser.rb
View file
_service:tar_scm:backport-CVE-2024-43398-upgrade-lib-rexml-to-3.3.6.patch
Added
@@ -0,0 +1,524 @@ +From 95871f399eda642a022b03550479b7994895c742 Mon Sep 17 00:00:00 2001 +From: Sutou Kouhei <kou@clear-code.com> +Date: Thu, 22 Aug 2024 09:54:49 +0900 +Subject: PATCH Add 3.3.6 entry + +--- + .bundle/gems/rexml-3.2.5/lib/rexml/element.rb | 30 ++-- + .bundle/gems/rexml-3.2.5/lib/rexml/entity.rb | 52 +------ + .../lib/rexml/parsers/baseparser.rb | 139 +++++++++++++----- + .../lib/rexml/parsers/streamparser.rb | 16 +- + .../lib/rexml/parsers/treeparser.rb | 7 - + .bundle/gems/rexml-3.2.5/lib/rexml/rexml.rb | 2 +- + 6 files changed, 131 insertions(+), 115 deletions(-) + +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb +index a5808d7..4e3a60b 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/element.rb +@@ -441,9 +441,14 @@ module REXML + # Related: #root_node, #document. + # + def root +- return elements1 if self.kind_of? Document +- return self if parent.kind_of? Document or parent.nil? +- return parent.root ++ target = self ++ while target ++ return target.elements1 if target.kind_of? Document ++ parent = target.parent ++ return target if parent.kind_of? Document or parent.nil? ++ target = parent ++ end ++ nil + end + + # :call-seq: +@@ -619,8 +624,12 @@ module REXML + else + prefix = "xmlns:#{prefix}" unless prefix0,5 == 'xmlns' + end +- ns = attributes prefix +- ns = parent.namespace(prefix) if ns.nil? and parent ++ ns = nil ++ target = self ++ while ns.nil? and target ++ ns = target.attributesprefix ++ target = target.parent ++ end + ns = '' if ns.nil? and prefix == 'xmlns' + return ns + end +@@ -2375,17 +2384,6 @@ module REXML + elsif old_attr.kind_of? Hash + old_attrvalue.prefix = value + elsif old_attr.prefix != value.prefix +- # Check for conflicting namespaces +- if value.prefix != "xmlns" and old_attr.prefix != "xmlns" +- old_namespace = old_attr.namespace +- new_namespace = value.namespace +- if old_namespace == new_namespace +- raise ParseException.new( +- "Namespace conflict in adding attribute \"#{value.name}\": "+ +- "Prefix \"#{old_attr.prefix}\" = \"#{old_namespace}\" and "+ +- "prefix \"#{value.prefix}\" = \"#{new_namespace}\"") +- end +- end + store value.name, {old_attr.prefix => old_attr, + value.prefix => value} + else +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb +index 573db69..12bbad3 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/entity.rb +@@ -12,6 +12,7 @@ module REXML + EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))" + NDATADECL = "\\s+NDATA\\s+#{NAME}" + PEREFERENCE = "%#{NAME};" ++ PEREFERENCE_RE = /#{PEREFERENCE}/um + ENTITYVALUE = %Q{((?:"(?:^%&"|#{PEREFERENCE}|#{REFERENCE})*")|(?:'(^%&'|#{PEREFERENCE}|#{REFERENCE})*'))} + PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})" + ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))" +@@ -19,7 +20,7 @@ module REXML + GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>" + ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um + +- attr_reader :name, :external, :ref, :ndata, :pubid ++ attr_reader :name, :external, :ref, :ndata, :pubid, :value + + # Create a new entity. Simple entities can be constructed by passing a + # name, value to the constructor; this creates a generic, plain entity +@@ -68,14 +69,11 @@ module REXML + end + + # Evaluates to the unnormalized value of this entity; that is, replacing +- # all entities -- both %ent; and &ent; entities. This differs from +- # +value()+ in that +value+ only replaces %ent; entities. ++ # &ent; entities. + def unnormalized + document.record_entity_expansion unless document.nil? +- v = value() +- return nil if v.nil? +- @unnormalized = Text::unnormalize(v, parent) +- @unnormalized ++ return nil if @value.nil? ++ @unnormalized = Text::unnormalize(@value, parent) + end + + #once :unnormalized +@@ -121,46 +119,6 @@ module REXML + write rv + rv + end +- +- PEREFERENCE_RE = /#{PEREFERENCE}/um +- # Returns the value of this entity. At the moment, only internal entities +- # are processed. If the value contains internal references (IE, +- # %blah;), those are replaced with their values. IE, if the doctype +- # contains: +- # <!ENTITY % foo "bar"> +- # <!ENTITY yada "nanoo %foo; nanoo> +- # then: +- # doctype.entity('yada').value #-> "nanoo bar nanoo" +- def value +- @resolved_value ||= resolve_value +- end +- +- def parent=(other) +- @resolved_value = nil +- super +- end +- +- private +- def resolve_value +- return nil if @value.nil? +- return @value unless @value.match?(PEREFERENCE_RE) +- +- matches = @value.scan(PEREFERENCE_RE) +- rv = @value.clone +- if @parent +- sum = 0 +- matches.each do |entity_reference| +- entity_value = @parent.entity( entity_reference0 ) +- if sum + entity_value.bytesize > Security.entity_expansion_text_limit +- raise "entity expansion has grown too large" +- else +- sum += entity_value.bytesize +- end +- rv.gsub!( /%#{entity_reference.join};/um, entity_value ) +- end +- end +- rv +- end + end + + # This is a set of entity constants -- the ones defined in the XML +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +index 44dc658..d11c276 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +@@ -1,12 +1,29 @@ + # frozen_string_literal: true + require_relative '../parseexception' + require_relative '../undefinednamespaceexception' ++require_relative '../security' + require_relative '../source' + require 'set' + require "strscan" + + module REXML + module Parsers ++ unless .respond_to?(:tally) ++ module EnumerableTally ++ refine Enumerable do ++ def tally ++ counts = {} ++ each do |item| ++ countsitem ||= 0 ++ countsitem += 1 ++ end ++ counts ++ end ++ end ++ end ++ using EnumerableTally ++ end ++ + if StringScanner::Version < "3.0.8" + module StringScannerCaptures + refine StringScanner do +@@ -124,6 +141,7 @@ module REXML + } + + module Private ++ PEREFERENCE_PATTERN = /#{PEREFERENCE}/um + TAG_PATTERN = /((?>#{QNAME_STR}))\s*/um + CLOSE_PATTERN = /(#{QNAME_STR})\s*>/um + ATTLISTDECL_END = /\s+#{NAME}(?:#{ATTDEF})*\s*>/um +@@ -163,7 +181,8 @@ module REXML + @tags =
View file
_service:tar_scm:backport-CVE-2024-47220.patch
Added
@@ -0,0 +1,62 @@ +From f5faca9222541591e1a7c3c97552ebb0c92733c7 Mon Sep 17 00:00:00 2001 +From: Jeremy Evans <code@jeremyevans.net> +Date: Wed, 18 Sep 2024 14:11:49 -0700 +Subject: PATCH Prevent request smuggling + +If a request has both a content-length and transfer-encoding +headers, return a 400 response. This is allowed by RFC 7230 +section 3.3.3.3. + +Fixes #145 +--- + tool/lib/webrick/httprequest.rb | 4 ++++ + tool/test/webrick/test_httprequest.rb | 18 ++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/tool/lib/webrick/httprequest.rb b/tool/lib/webrick/httprequest.rb +index 5cf5844..820acb2 100644 +--- a/tool/lib/webrick/httprequest.rb ++++ b/tool/lib/webrick/httprequest.rb +@@ -474,6 +474,10 @@ module WEBrick + def read_body(socket, block) + return unless socket + if tc = self'transfer-encoding' ++ if self'content-length' ++ raise HTTPStatus::BadRequest, "request with both transfer-encoding and content-length, possible request smuggling" ++ end ++ + case tc + when /\Achunked\z/io then read_chunked(socket, block) + else raise HTTPStatus::NotImplemented, "Transfer-Encoding: #{tc}." +diff --git a/tool/test/webrick/test_httprequest.rb b/tool/test/webrick/test_httprequest.rb +index 855ff9d..cce9b91 100644 +--- a/tool/test/webrick/test_httprequest.rb ++++ b/tool/test/webrick/test_httprequest.rb +@@ -81,6 +81,24 @@ GET / + } + end + ++ def test_content_length_and_transfer_encoding_headers_smuggling ++ msg = <<~HTTP.gsub("\n", "\r\n") ++ POST /user HTTP/1.1 ++ Content-Length: 28 ++ Transfer-Encoding: chunked ++ ++ 0 ++ ++ GET /admin HTTP/1.1 ++ ++ HTTP ++ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) ++ req.parse(StringIO.new(msg)) ++ assert_raise(WEBrick::HTTPStatus::BadRequest){ ++ req.body ++ } ++ end ++ + def test_parse_headers + msg = <<-_end_of_message_ + GET /path HTTP/1.1 +-- +2.27.0 +
View file
_service:tar_scm:backport-CVE-2024-49761.patch
Added
@@ -0,0 +1,38 @@ +From ce59f2eb1aeb371fe1643414f06618dbe031979f Mon Sep 17 00:00:00 2001 +From: Sutou Kouhei <kou@clear-code.com> +Date: Thu, 24 Oct 2024 14:45:31 +0900 +Subject: PATCH parser: fix a bug that �x...; is accepted as a character + reference + + +diff --git a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +index 7bd8adf..b4547ba 100644 +--- a/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb ++++ b/.bundle/gems/rexml-3.2.5/lib/rexml/parsers/baseparser.rb +@@ -150,7 +150,7 @@ module REXML + PEDECL_PATTERN = "\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>" + ENTITYDECL_PATTERN = /(?:#{GEDECL_PATTERN})|(?:#{PEDECL_PATTERN})/um + CARRIAGE_RETURN_NEWLINE_PATTERN = /\r\n?/ +- CHARACTER_REFERENCES = /�*((?:\d+)|(?:xa-fA-F0-9+));/ ++ CHARACTER_REFERENCES = /&#((?:\d+)|(?:xa-fA-F0-9+));/ + DEFAULT_ENTITIES_PATTERNS = {} + default_entities = 'gt', 'lt', 'quot', 'apos', 'amp' + default_entities.each do |term| +@@ -570,8 +570,12 @@ module REXML + return rv if matches.size == 0 + rv.gsub!( Private::CHARACTER_REFERENCES ) { + m=$1 +- m = "0#{m}" if m0 == ?x +- Integer(m).pack('U*') ++ if m.start_with?("x") ++ code_point = Integer(m1..-1, 16) ++ else ++ code_point = Integer(m, 10) ++ end ++ code_point.pack('U*') + } + matches.collect!{|x|x0}.compact! + if filter +-- +2.27.0 +
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="tar_scm"> <param name="scm">git</param> <param name="url">git@gitee.com:src-openeuler/ruby.git</param> - <param name="revision">openEuler-24.03-LTS-Next</param> + <param name="revision">openEuler-24.03-LTS-SP1</param> <param name="exclude">*</param> <param name="extract">*</param> </service>
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2