File: uri.rb

package info (click to toggle)
ruby-data-uri 0.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 76 kB
  • sloc: ruby: 81; makefile: 3
file content (66 lines) | stat: -rw-r--r-- 1,844 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
module URI

  class Data < Generic

    COMPONENT = [:scheme, :opaque].freeze
    MIME_TYPE_RE = %r{^([-\w.+]+/[-\w.+]*)}.freeze
    MIME_PARAM_RE = /^;([-\w.+]+)=([^;,]+)/.freeze

    attr_reader :content_type, :data

    def initialize(*args)
      if args.length == 1
        uri = args.first.to_s
        unless uri.match(/^data:/)
          raise URI::InvalidURIError.new('Invalid Data URI: ' + args.first.inspect)
        end
        @scheme = 'data'
        @opaque = uri[5 .. -1]
      else
        super(*args)
      end
      @data = @opaque
      if md = MIME_TYPE_RE.match(@data)
        @content_type = md[1]
        @data = @data[@content_type.length .. -1]
      end
      @content_type ||= 'text/plain'
      @mime_params = {}
      while md = MIME_PARAM_RE.match(@data)
        @mime_params[md[1]] = md[2]
        @data = @data[md[0].length .. -1]
      end
      if base64 = /^;base64/.match(@data)
        @data = @data[7 .. -1]
      end
      unless /^,/.match(@data)
        raise URI::InvalidURIError.new('Invalid data URI')
      end
      @data = @data[1 .. -1]
      @data = base64 ? Base64.decode64(@data) : URI.decode(@data)
      if @data.respond_to?(:force_encoding) && charset = @mime_params['charset']
        @data.force_encoding(charset)
      end
    end

    def self.build(arg)
      data = nil
      content_type = nil
      case arg
        when IO
          data = arg
        when Hash
          data = arg[:data]
          content_type = arg[:content_type]
      end
      raise 'Invalid build argument: ' + arg.inspect unless data
      if !content_type && data.respond_to?(:content_type)
        content_type = data.content_type
      end
      new('data', nil, nil, nil, nil, nil, "#{content_type};base64,#{Base64.encode64(data.read).chop}", nil, nil)
    end
  end

  @@schemes['DATA'] = Data

end