File indexing completed on 2024-04-14 05:02:33

0001 # frozen_string_literal: true
0002 #
0003 # Copyright (C) 2016 Harald Sitter <sitter@kde.org>
0004 #
0005 # This library is free software; you can redistribute it and/or
0006 # modify it under the terms of the GNU Lesser General Public
0007 # License as published by the Free Software Foundation; either
0008 # version 2.1 of the License, or (at your option) version 3, or any
0009 # later version accepted by the membership of KDE e.V. (or its
0010 # successor approved by the membership of KDE e.V.), which shall
0011 # act as a proxy defined in Section 6 of version 3 of the license.
0012 #
0013 # This library is distributed in the hope that it will be useful,
0014 # but WITHOUT ANY WARRANTY; without even the implied warranty of
0015 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016 # Lesser General Public License for more details.
0017 #
0018 # You should have received a copy of the GNU Lesser General Public
0019 # License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0020 
0021 require 'insensitive_hash/minimal'
0022 
0023 require_relative 'deb822'
0024 
0025 module Debian
0026   # Debian .dsc parser
0027   class DSC < Deb822
0028     # FIXME: lazy read automatically when accessing fields
0029     attr_reader :fields
0030 
0031     File = Struct.new(:md5, :size, :name)
0032     Checksum = Struct.new(:sum, :size, :file_name)
0033 
0034     # FIXME: pretty sure that should be in the base
0035     def initialize(file)
0036       @file = file
0037       @fields = InsensitiveHash.new
0038     end
0039 
0040     def parse!
0041       lines = ::File.new(@file).readlines
0042 
0043       fields = { mandatory: %w(format source version maintainer
0044                                checksums-sha1 checksums-sha256 files),
0045                  relationship: %w(build-depends build-depends-indep
0046                                   build-conflicts build-conflicts-indep),
0047                  multiline: %w(checksums-sha1 checksums-sha256 files) }
0048       fields[:foldable] = %w(package-list binary) + fields[:relationship]
0049       @fields = parse_paragraph(lines, fields)
0050       post_process
0051 
0052       # TODO: Strip custom fields and add a Control::flags_for(entry) method.
0053 
0054       # FIXME: signing verification not implemented
0055       #   this code works; needs to be somewhere generic
0056       #   also needs to rescue GPGME::Error::NoData
0057       #   in case the file is not signed
0058       # crypto = GPGME::Crypto.new
0059       # results = []
0060       # crypto.verify(data) do |signature|
0061       #   results << signature.valid?
0062       #
0063       # !results.empty? && results.all?
0064     end
0065 
0066     private
0067 
0068     def post_process
0069       return unless @fields
0070       if @fields['files']
0071         # Mangle list fields into structs.
0072         @fields['files'] = parse_types(@fields['files'], File)
0073         %w(checksums-sha1 checksums-sha256).each do |key|
0074           @fields[key] = parse_types(fields[key], Checksum)
0075         end
0076       end
0077 
0078       return unless @fields.key?('package-list')
0079       @fields['package-list'].reject! { |x| x.respond_to?(:empty?) && x.empty? }
0080     end
0081 
0082     def parse_types(lines, klass)
0083       lines.split($/).collect do |line|
0084         klass.new(*line.split(' '))
0085       end
0086     end
0087   end
0088 end