printsly 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +13 -5
- data/bin/printsly +32 -28
- data/lib/common_stuff.rb +33 -36
- data/lib/menu.rb +39 -23
- data/lib/printers.rb +45 -31
- data/lib/printsly.rb +2 -0
- data/lib/show_text.rb +62 -0
- metadata +18 -17
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YWE1YTQ0MTdhNmMzYmEzMmEwODdjNmEwNjUxZjNiNzg3ODMxNWIzZA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZmIxZDRmM2EzMzE5MDlmYjMxZjBmZmIzNWY4NTEwZWVhZGViZGI4MA==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NWQyODdmZjFkODA4MjFlNWYxNDNlOTA4ZTI5OTI3MGYwYTU0ZWIyMDE1N2Q5
|
10
|
+
NDNlMzg5ZWEwM2ZjMDYzYjBjMzM3YTQ2NGU0YmY5OTg1MWQ4ZGQ3OTg3ZGEz
|
11
|
+
MjNkYzA4NTE1MGMwMmJmY2YyNjA1NjdjZjlhMWNiNWNkM2MxNDM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZTg1Zjk3NmIwZGM3Y2Q3OTkwNjUwYjA0ZDZmNmYxYWVhOThkNmQzNTYzNGM0
|
14
|
+
ODIyMWM2NWUxNWM5NGJjOTFmOTMxNmFlOWI5Y2ExY2VmOGQzNDA2MjM4NmVl
|
15
|
+
MjZhNmQyZWZmYWYxZTNhOGVkMzIzMGJmMjA3OGY0YTc2MDFkYTE=
|
data/bin/printsly
CHANGED
@@ -5,45 +5,49 @@ require 'printsly'
|
|
5
5
|
v = ARGV
|
6
6
|
case
|
7
7
|
when v.empty? == true
|
8
|
+
puts
|
8
9
|
puts bar_top.yellow
|
9
10
|
puts " "*24 + "Helps you add printers to CUPS".yellow + " "*19
|
10
11
|
puts bar_low.yellow
|
11
|
-
puts #
|
12
|
+
puts # format
|
12
13
|
puts "Selectable options will normally be enclosed in " + "[ ]".yellow + "'s."
|
13
|
-
puts #
|
14
|
+
puts # format
|
14
15
|
Menu.new.choices
|
15
|
-
when v.count >
|
16
|
-
|
17
|
-
puts "Please pass only one directory at a time!".red
|
18
|
-
puts # formatting
|
16
|
+
when v.count > 2
|
17
|
+
help_text
|
19
18
|
exit 1 #something went wrong
|
20
|
-
when v.count
|
21
|
-
|
19
|
+
when v.count == 1
|
20
|
+
help_text
|
21
|
+
exit 1 #soemthing went wrong
|
22
|
+
when v.count == 2
|
23
|
+
v.each do |dirk| #basic directory verification
|
22
24
|
if /^\//.match(dirk) #does path start at root?
|
23
|
-
|
24
|
-
|
25
|
-
puts #
|
26
|
-
|
27
|
-
puts # formatting
|
25
|
+
unless Dir.exists?(dirk)
|
26
|
+
puts # format
|
27
|
+
puts "#{dirk} does not exist!".red
|
28
|
+
help_text
|
28
29
|
exit 1 #something went wrong
|
29
|
-
when true
|
30
|
-
spreads = Dir.glob(File.join(dirk, '*.xls'))
|
31
|
-
case spreads.size > 0
|
32
|
-
when true
|
33
|
-
spreads.each do |sheety|
|
34
|
-
Printers.new.build(sheety)
|
35
|
-
end
|
36
|
-
when false
|
37
|
-
puts # formatting
|
38
|
-
puts "There are no spreadsheets in specified directory!".red
|
39
|
-
puts # formatting
|
40
|
-
end
|
41
30
|
end
|
42
31
|
else
|
43
|
-
|
44
|
-
puts "Please pass the full path to the directory you wish to process and nothing else!".red
|
45
|
-
puts # formatting
|
32
|
+
help_text
|
46
33
|
exit 1 #something went wrong
|
47
34
|
end
|
48
35
|
end
|
36
|
+
spreads = Dir.glob(File.join(v[0], '*.xls'))
|
37
|
+
case spreads.size > 0
|
38
|
+
when true
|
39
|
+
spreads.each do |sheety|
|
40
|
+
hosty = `hostname`.strip
|
41
|
+
sheet = sheety + "." + hosty
|
42
|
+
cur_conf = fill_hash sheety, "On", "On"
|
43
|
+
unless File.exists?(sheet)
|
44
|
+
Batch.new.process(cur_conf)
|
45
|
+
system "bash", "-c", "touch #{sheet}" if $green == true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
when false
|
49
|
+
puts # formatting
|
50
|
+
puts "There are no spreadsheets in #{v[0]}!".red
|
51
|
+
puts # formatting
|
52
|
+
end
|
49
53
|
end
|
data/lib/common_stuff.rb
CHANGED
@@ -1,12 +1,40 @@
|
|
1
1
|
module CommonStuff
|
2
2
|
|
3
3
|
@@config_file = File.join(Dir.home, "printsly.json")
|
4
|
+
@@prov_log = "/var/log/cups/provision_log"
|
4
5
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
def log_file
|
7
|
+
if Dir.exists?("/var/log/cups")
|
8
|
+
File.new(@@prov_log, "w+") unless File.exists?(@@prov_log)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def log_entry printerdata, status
|
13
|
+
if File.exists?(@@prov_log)
|
14
|
+
log_entry_write(printerdata, status)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def log_entry_write printerdata, status
|
19
|
+
File.open(@@prov_log, "a") do |f|
|
20
|
+
f.puts log_entry_data_woot(printerdata) if status == 0
|
21
|
+
f.puts log_entry_data_fail(printerdata) if status == 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def log_entry_data_woot printerdata
|
26
|
+
timey = Time.new
|
27
|
+
"Add: " + timey.inspect + " " + printerdata[0] + " " + printerdata[2] + " IP: " + printerdata[1]
|
28
|
+
end
|
29
|
+
|
30
|
+
def log_entry_data_fail printerdata
|
31
|
+
timey = Time.new
|
32
|
+
"FAILED: " + timey.inspect + " " + printerdata[0] + " " + printerdata[2] + " IP: " + printerdata[1]
|
33
|
+
end
|
34
|
+
|
35
|
+
def mod_name namey, store
|
36
|
+
namey = "0" + store + namey if namey.include?('RT') || namey.include?('SIM')
|
37
|
+
namey
|
10
38
|
end
|
11
39
|
|
12
40
|
def prompt
|
@@ -28,14 +56,6 @@ module CommonStuff
|
|
28
56
|
prompt; gets.chomp
|
29
57
|
end
|
30
58
|
|
31
|
-
def bar_top
|
32
|
-
"_"*34 + " " + "Printsly" + " " + "_"*34
|
33
|
-
end
|
34
|
-
|
35
|
-
def bar_low
|
36
|
-
"-"*78
|
37
|
-
end
|
38
|
-
|
39
59
|
def fill_hash work_dir, batchy, auto_mater
|
40
60
|
cur_conf = Hash.new
|
41
61
|
cur_conf[:work_dir] = work_dir
|
@@ -56,27 +76,4 @@ module CommonStuff
|
|
56
76
|
end
|
57
77
|
end
|
58
78
|
|
59
|
-
def work_dir_text
|
60
|
-
puts #format
|
61
|
-
puts "The " + "working directory".yellow + " is the location " + "Printsly".yellow + " will look for"
|
62
|
-
puts "spreadsheets containing printers to add to " + "CUPS".yellow + "."
|
63
|
-
end
|
64
|
-
|
65
|
-
def batchy_text
|
66
|
-
puts #format
|
67
|
-
puts "Batch mode".yellow + " means all spreadsheets in the " + "working directory".yellow + " will be processed."
|
68
|
-
end
|
69
|
-
|
70
|
-
def auto_text
|
71
|
-
puts #format
|
72
|
-
puts "Auto provision".yellow + " means provisioning is done immediately with no"
|
73
|
-
puts "confirmation dialogue."
|
74
|
-
end
|
75
|
-
|
76
|
-
def welcome_text
|
77
|
-
puts "If this is the first time to run Printsly, please choose " + "[3]".yellow + " and configure."
|
78
|
-
puts #format
|
79
|
-
puts "The configuration file is stored in your home directory by default."
|
80
|
-
end
|
81
|
-
|
82
79
|
end
|
data/lib/menu.rb
CHANGED
@@ -41,33 +41,15 @@ class Menu
|
|
41
41
|
def actions move
|
42
42
|
case
|
43
43
|
when move == "1"
|
44
|
-
|
45
|
-
spread = choose_file
|
46
|
-
puts #formatting
|
47
|
-
puts "You have chosen " + spread.yellow + ". Is this correct?"
|
48
|
-
yes_no
|
49
|
-
end while not (@yes_no == "yes")
|
50
|
-
Printers.new.build(spread)
|
44
|
+
singleton(@cur_conf)
|
51
45
|
when move == "2"
|
52
46
|
Batch.new.process(@cur_conf)
|
53
47
|
when move == "3"
|
54
48
|
@cur_conf = Configurator.new.choices(@cur_conf)
|
55
49
|
when move == "4"
|
56
|
-
|
57
|
-
puts "Current Working Directory: " + @cur_conf[:work_dir].green
|
58
|
-
puts "Current Batch Mode Setting: " + @cur_conf[:batchy].green
|
59
|
-
puts "Current Auto Provision Setting: " + @cur_conf[:auto_mater].green
|
50
|
+
show_conf(@cur_conf)
|
60
51
|
when move == "5"
|
61
|
-
|
62
|
-
puts "Resetting to default configuration...".yellow
|
63
|
-
sleep(0.5)
|
64
|
-
puts "...".yellow
|
65
|
-
sleep(0.5)
|
66
|
-
puts "......".red
|
67
|
-
@cur_conf = fill_hash("Not Set", "Off", "Off")
|
68
|
-
save_config(@cur_conf)
|
69
|
-
sleep(0.5)
|
70
|
-
puts ".........done!".green
|
52
|
+
@cur_conf = reset_conf(@cur_conf)
|
71
53
|
when move == "6"
|
72
54
|
# leave application
|
73
55
|
puts #format
|
@@ -77,6 +59,41 @@ class Menu
|
|
77
59
|
end
|
78
60
|
end
|
79
61
|
|
62
|
+
def reset_conf cur_conf
|
63
|
+
puts #format
|
64
|
+
puts "Resetting to default configuration...".yellow
|
65
|
+
sleep(0.5)
|
66
|
+
puts "...".yellow
|
67
|
+
sleep(0.5)
|
68
|
+
puts "......".red
|
69
|
+
cur_conf = fill_hash("Not Set", "Off", "Off")
|
70
|
+
save_config(cur_conf) if File.exists?(File.join(Dir.home, "printsly.json"))
|
71
|
+
sleep(0.5)
|
72
|
+
puts ".........done!".green
|
73
|
+
cur_conf
|
74
|
+
end
|
75
|
+
|
76
|
+
def show_conf cur_conf
|
77
|
+
puts #format
|
78
|
+
puts "Current Working Directory: " + cur_conf[:work_dir].green
|
79
|
+
puts "Current Batch Mode Setting: " + cur_conf[:batchy].green
|
80
|
+
puts "Current Auto Provision Setting: " + cur_conf[:auto_mater].green
|
81
|
+
end
|
82
|
+
|
83
|
+
def singleton cur_conf
|
84
|
+
begin
|
85
|
+
spread = choose_file
|
86
|
+
puts #formatting
|
87
|
+
puts "You have chosen " + spread.yellow + ". Is this correct?"
|
88
|
+
yes_no
|
89
|
+
end while not (@yes_no == "yes")
|
90
|
+
book = Spreadsheet.open spread
|
91
|
+
sheet = book.worksheet 0
|
92
|
+
store = sheet.row(0)[0][6..8]
|
93
|
+
printers = Printers.new.hashy(sheet, store)
|
94
|
+
Printers.new.provision(printers, store)
|
95
|
+
end
|
96
|
+
|
80
97
|
end
|
81
98
|
|
82
99
|
class Batch
|
@@ -92,13 +109,12 @@ class Batch
|
|
92
109
|
end
|
93
110
|
puts "Processing " + cur_conf[:work_dir].yellow + ":"
|
94
111
|
sleep(0.5)
|
95
|
-
#Printers.new.batch(cur_conf[:work_dir]) This will be used once Printers::Batch is built
|
96
112
|
puts "...".yellow
|
97
113
|
sleep(0.5)
|
98
114
|
puts "......".red
|
99
115
|
sleep(0.5)
|
100
116
|
puts ".........done!".green
|
101
|
-
Printers.new.
|
117
|
+
Printers.new.batch(cur_conf[:work_dir])
|
102
118
|
end
|
103
119
|
|
104
120
|
end
|
data/lib/printers.rb
CHANGED
@@ -1,51 +1,65 @@
|
|
1
1
|
class Printers
|
2
|
-
attr_accessor :store_printers
|
3
|
-
|
4
|
-
def initialize
|
5
|
-
puts
|
6
|
-
puts "Let's get started."
|
7
|
-
puts
|
8
|
-
end
|
9
|
-
|
10
|
-
def build spread
|
2
|
+
#attr_accessor :store_printers
|
11
3
|
|
4
|
+
def batch spread
|
12
5
|
book = Spreadsheet.open spread
|
13
6
|
sheet1 = book.worksheet 0
|
14
7
|
store = sheet1.row(0)[0][6..8]
|
15
|
-
printers =
|
16
|
-
|
8
|
+
printers = hashy(sheet1, store)
|
9
|
+
provision(printers, store)
|
10
|
+
printers
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def hashy sheet, store
|
18
|
+
store_printers = Hash.new
|
19
|
+
sheet.each 5 do |row|
|
17
20
|
break if row[0].nil?
|
18
21
|
printername = row[4]
|
19
22
|
if printername != nil
|
20
|
-
|
21
|
-
printer = Array.new
|
22
|
-
printer = printer.push row[4] # name
|
23
|
-
printer = printer.push row[5] # ip address
|
24
|
-
printer = printer.push row[3] # Model
|
25
|
-
printer = printer.push row[0] # Description
|
26
|
-
printers[printername] = printer
|
27
|
-
end
|
23
|
+
store_printers[printername] = printer(row, printername, store)
|
28
24
|
end
|
29
25
|
end
|
26
|
+
store_printers
|
27
|
+
end
|
30
28
|
|
29
|
+
def show_printers printers, store
|
31
30
|
puts
|
32
|
-
puts
|
31
|
+
puts prov_text(store)
|
33
32
|
puts
|
33
|
+
printers.each do | printername, printerdata |
|
34
|
+
printerdata[0] = mod_name(printerdata[0], store)
|
35
|
+
puts printer_puts(printerdata)
|
36
|
+
end
|
37
|
+
end
|
34
38
|
|
35
|
-
|
36
|
-
|
39
|
+
def printer row, printername, store
|
40
|
+
if printername.include?(store) || printername.include?('RT') || printername.include?('SIM')
|
41
|
+
printer = Array.new
|
42
|
+
printer = printer.push row[4] # name
|
43
|
+
printer = printer.push row[5] # ip address
|
44
|
+
printer = printer.push row[3] # Model
|
45
|
+
printer = printer.push row[0] # Description
|
46
|
+
printer
|
37
47
|
end
|
48
|
+
end
|
38
49
|
|
50
|
+
def provision printers, store
|
51
|
+
log_file
|
52
|
+
$green = true
|
39
53
|
printers.each do | printername, printerdata |
|
40
|
-
printerdata[0] =
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
54
|
+
printerdata[0] = mod_name(printerdata[0], store)
|
55
|
+
lp_command = lpadmin_puts(printerdata)
|
56
|
+
system "bash", "-c", lp_command
|
57
|
+
if $?.exitstatus > 0
|
58
|
+
puts "I failed to add #{printerdata[0]}!" # for CLI output
|
59
|
+
$green = false
|
60
|
+
log_entry(printerdata, 1)
|
61
|
+
else
|
62
|
+
log_entry(printerdata, 0)
|
49
63
|
end
|
50
64
|
end
|
51
65
|
end
|
data/lib/printsly.rb
CHANGED
data/lib/show_text.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
module ShowText
|
2
|
+
|
3
|
+
def auto_text
|
4
|
+
puts #format
|
5
|
+
puts "Auto provision".yellow + " means provisioning is done immediately with no"
|
6
|
+
puts "confirmation dialogue."
|
7
|
+
end
|
8
|
+
|
9
|
+
def bar_both
|
10
|
+
puts # format
|
11
|
+
puts bar_top.yellow
|
12
|
+
puts bar_low.yellow
|
13
|
+
puts # format
|
14
|
+
end
|
15
|
+
|
16
|
+
def bar_low
|
17
|
+
"-"*78
|
18
|
+
end
|
19
|
+
|
20
|
+
def bar_top
|
21
|
+
"_"*34 + " " + "Printsly" + " " + "_"*34
|
22
|
+
end
|
23
|
+
|
24
|
+
def batchy_text
|
25
|
+
puts #format
|
26
|
+
puts "Batch mode".yellow + " means all spreadsheets in the " + "working directory".yellow + " will be processed."
|
27
|
+
end
|
28
|
+
|
29
|
+
def help_text
|
30
|
+
puts # format
|
31
|
+
puts "Please pass the FULL PATH for two directories separated by a space!".red
|
32
|
+
puts "Pending files in the first directory and done in the second.".red
|
33
|
+
puts # format
|
34
|
+
puts "EXAMPLE: printsly /u01/app/cups/pending /u01/app/cups/done".green
|
35
|
+
puts # format
|
36
|
+
end
|
37
|
+
|
38
|
+
def lpadmin_puts printerdata
|
39
|
+
"lpadmin -p " + printerdata[0] + " -L \"" + printerdata[3] + "\" -D \"" + printerdata[2] + "\" -E -v socket://" + printerdata[1] + ":9100 -m raw"
|
40
|
+
end
|
41
|
+
|
42
|
+
def prov_text store
|
43
|
+
"This is what I am planning on provisioning for store " + store + ":"
|
44
|
+
end
|
45
|
+
|
46
|
+
def printer_puts printerdata
|
47
|
+
"Name: ".yellow + printerdata[0] + " " + "Type: ".yellow + printerdata[2] + " " + "IP: ".yellow + printerdata[1] + " " + "Desc: ".yellow + printerdata[3]
|
48
|
+
end
|
49
|
+
|
50
|
+
def welcome_text
|
51
|
+
puts "If this is the first time to run Printsly, please choose " + "[3]".yellow + " and configure."
|
52
|
+
puts #format
|
53
|
+
puts "The configuration file is stored in your home directory by default."
|
54
|
+
end
|
55
|
+
|
56
|
+
def work_dir_text
|
57
|
+
puts #format
|
58
|
+
puts "The " + "working directory".yellow + " is the location " + "Printsly".yellow + " will look for"
|
59
|
+
puts "spreadsheets containing printers to add to " + "CUPS".yellow + "."
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: printsly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kody Wilson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: spreadsheet
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 1.0.3
|
20
|
-
- -
|
20
|
+
- - ! '>='
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: 1.0.3
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 1.0.3
|
30
|
-
- -
|
30
|
+
- - ! '>='
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.0.3
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: colorize
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- -
|
37
|
+
- - ~>
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.7.
|
40
|
-
- -
|
39
|
+
version: 0.7.7
|
40
|
+
- - ! '>='
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: 0.7.
|
42
|
+
version: 0.7.7
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- -
|
47
|
+
- - ~>
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 0.7.
|
50
|
-
- -
|
49
|
+
version: 0.7.7
|
50
|
+
- - ! '>='
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: 0.7.
|
52
|
+
version: 0.7.7
|
53
53
|
description: Helps you add printers to CUPS
|
54
54
|
email: kodywilson@gmail.com
|
55
55
|
executables:
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- lib/menu.rb
|
64
64
|
- lib/printers.rb
|
65
65
|
- lib/printsly.rb
|
66
|
+
- lib/show_text.rb
|
66
67
|
homepage: https://github.com/kodywilson/printsly
|
67
68
|
licenses:
|
68
69
|
- MIT
|
@@ -73,17 +74,17 @@ require_paths:
|
|
73
74
|
- lib
|
74
75
|
required_ruby_version: !ruby/object:Gem::Requirement
|
75
76
|
requirements:
|
76
|
-
- -
|
77
|
+
- - ! '>='
|
77
78
|
- !ruby/object:Gem::Version
|
78
79
|
version: '0'
|
79
80
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
81
|
requirements:
|
81
|
-
- -
|
82
|
+
- - ! '>='
|
82
83
|
- !ruby/object:Gem::Version
|
83
84
|
version: '0'
|
84
85
|
requirements: []
|
85
86
|
rubyforge_project:
|
86
|
-
rubygems_version: 2.
|
87
|
+
rubygems_version: 2.4.8
|
87
88
|
signing_key:
|
88
89
|
specification_version: 4
|
89
90
|
summary: Printer management software
|