-
Notifications
You must be signed in to change notification settings - Fork 1
/
airprint-ppd.zsh
executable file
·282 lines (234 loc) · 8.75 KB
/
airprint-ppd.zsh
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#!/bin/zsh
#
# Tool to generate a proper PPD and Icon file for a given AirPrint supported printer
#
# Special props to:
# Kevin M. Cox: https://www.kevinmcox.com/2020/12/airprint-generator/
# Apizz: https://aporlebeke.wordpress.com/2019/10/30/configuring-printers-programmatically-for-airprint/
#
# Author: choules@wycomco.de
# Last Update: 2022-02-25
#
##################################################################
VERSION="1.2.0"
ICNS_COPY_DIR=""
PPD_OUTPUT_DIR="/Library/Printers/PPDs/Contents/Resources"
PRINTER_URL=""
OUTPUT_NAME=""
SECURE_MODE=false
SCRIPT_NAME=`basename $0`
IPP2PPD="/System/Library/Printers/Libraries/ipp2ppd"
IPPTOOL="/usr/bin/ipptool"
AIRPRINT_PPD="/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/Resources/AirPrint.ppd"
usage() {
cat <<EOF
Usage: ${SCRIPT_NAME} -p printer_url [-i icns_copy_dir] [-o ppd_output_dir] [-n name] [-s] [-v]
This script queries the given printer url for a PPD and handles the icon generation, so that it may
be run as root. A printer icon will be generated and saved to the default location with the expected
name containing the printers UUID. You may optionally save a copy of the icons file to a different
location.
-p printer_url IPP URL, for example ipp://FNCYPRINT.local or ipp://192.168.1.244:443, mandatory
-i icns_copy_dir Output dir for copy of icon, required if not running with root privileges
-o ppd_output_dir Output dir for PPD, required if not running with root privileges.
For root user this defaults to /Library/Printers/PPDs/Contents/Resources
-n name Name to be used for icon and ppd file, defaults to queried model name
-s Switch to secure mode, which won't ignore untrusted TLS certificates
-v Display current version
-h Show this usage message
EOF
}
get_ppd_string() {
cat "$1" | grep -i "$2" | awk -F ": " '{ print $2 }' | tr -d '"'
}
get_ippinfo_string() {
cat "$1" | grep -i "$2" | awk -F " = " '{ print $2 }'
}
while getopts "p:i:o:n:svh" option
do
case $option in
"p")
PRINTER_URL="$OPTARG"
;;
"i")
ICNS_COPY_DIR="$OPTARG"
;;
"o")
PPD_OUTPUT_DIR="$OPTARG"
;;
"n")
OUTPUT_NAME="$OPTARG"
;;
"s")
SECURE_MODE=true
;;
"v")
echo ${VERSION}
exit 1
;;
"h" | *)
usage
exit 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -ne 0 ]; then
usage
exit 1
fi
if [ "${PRINTER_URL}" = "" ]; then
echo "ERROR: No Printer URL given" 1>&2
echo ""
usage
exit 2
fi
case "$PRINTER_URL" in
*/)
;;
*)
PRINTER_URL="${PRINTER_URL}/"
;;
esac
if [ "${ICNS_COPY_DIR}" != "" ] && [ ! -d "${ICNS_COPY_DIR}" ]; then
echo "ERROR: Provided icns_copy_dir not a valid directory" 1>&2
echo ""
usage
exit 3
fi
if [ "${ICNS_COPY_DIR}" = "" ] && [ $EUID -ne 0 ]; then
echo "You have not provided a icns_copy_dir. Since you are not running this command as root"
echo "we will not be able to save the icns file to its default location. Please specify a"
echo "writeable icns_copy_dir."
echo ""
usage
exit 4
fi
if [ "${PPD_OUTPUT_DIR}" != "" ] && [ ! -d "${PPD_OUTPUT_DIR}" ]; then
echo "ERROR: Provided ppd_output_dir not a valid directory" 1>&2
echo ""
usage
exit 5
fi
if [ "${PPD_OUTPUT_DIR}" = "" ] && [ $EUID -ne 0 ]; then
echo "You have not provided a ppd_output_dir. Since you are not running this command as root"
echo "we will not be able to save the ppd file to its default location. Please specify a"
echo "writeable ppd_output_dir."
echo ""
usage
exit 6
fi
echo "Creating a temporary working directory..."
TEMP_DIR=`mktemp -d`
if [ $? -ne 0 ]; then
echo "$0: Can't create temporary directory, exiting..."
exit 500
fi
echo "Created temporary directory at: ${TEMP_DIR}"
PPD_FILE="${TEMP_DIR}/printer.ppd"
echo "Fetching the PPD using ipp2ppd..."
"${IPP2PPD}" "${PRINTER_URL}" "${AIRPRINT_PPD}" > "${PPD_FILE}"
if [ ! -s "${PPD_FILE}" ]; then
echo "ERROR: Fetched PPD is empty..."
exit 404
fi
MODEL_NAME=`get_ppd_string "${PPD_FILE}" "ModelName"`
MANUFACTURER=`get_ppd_string "${PPD_FILE}" "Manufacturer"`
DEFAULT_ICON_PATH=`get_ppd_string "${PPD_FILE}" "APPrinterIconPath"`
IPPINFO_FILE="${TEMP_DIR}/ippinfo"
if [ "${OUTPUT_NAME}" = "" ]; then
OUTPUT_NAME="${MODEL_NAME}"
fi
echo "Fetching the IPP attributes using ipptool..."
"${IPPTOOL}" -tv "${PRINTER_URL}" get-printer-attributes.test > "${IPPINFO_FILE}"
if [ $? -ne 0 ]; then
echo "$0: Can't fetch IPP attributes, exiting..."
exit 1
fi
if [ ! -s "${IPPINFO_FILE}" ]; then
echo "ERROR: Fetched IPP info is empty..."
exit 500
fi
PRINTER_NAME=`get_ippinfo_string "${IPPINFO_FILE}" "printer-name (nameWithoutLanguage) ="`
PRINTER_LOCATION=`get_ippinfo_string "${IPPINFO_FILE}" "printer-location (textWithoutLanguage) = "`
PRINTER_ICONS_STRING=`get_ippinfo_string "${IPPINFO_FILE}" "printer-icons (1setOf uri) ="`
PRINTER_ICONS=(${(s:,:)PRINTER_ICONS_STRING})
ICON_DIR="${TEMP_DIR}/icons"
IMAGESET_DIR="${ICON_DIR}/printer.iconset"
ICNS_TMP_FILE="${ICON_DIR}/printer.icns"
mkdir -p "${IMAGESET_DIR}"
for ICON_URL in $PRINTER_ICONS
do
IMAGE_FILE_NAME=`basename $ICON_URL`
echo "Downloading the printer image file ${IMAGE_FILE_NAME}..."
if [ "$SECURE_MODE" = true ]; then
curl -s -o "${ICON_DIR}/${IMAGE_FILE_NAME}" $ICON_URL
CURL_RESULT=$?
else
curl -s -k -o "${ICON_DIR}/${IMAGE_FILE_NAME}" $ICON_URL
CURL_RESULT=$?
fi
if [ $CURL_RESULT -ne 0 ]; then
if [ $CURL_RESULT -eq 60 ]; then
echo "Error downloading image ${IMAGE_FILE_NAME} due to missing trust info."
echo "Please consider to not use the -s option if you are trusting the url"
echo "${ICON_URL}"
else
echo "Error downloading image ${ICON_URL}."
fi
else
IMAGE_RESOLUTION=`file "${ICON_DIR}/${IMAGE_FILE_NAME}" | awk -F "," '{print $2}' | tr -d ' '`
echo "This image has the following dimensions: $IMAGE_RESOLUTION"
SIZE=`echo ${IMAGE_RESOLUTION} | awk -F "x" '{print $1}'`
echo "Adding this image to the temporary macOS iconset..."
case "$SIZE" in
16)
mv "${ICON_DIR}/${IMAGE_FILE_NAME}" "${IMAGESET_DIR}/icon_16x16.png"
;;
32)
mv "${ICON_DIR}/${IMAGE_FILE_NAME}" "${IMAGESET_DIR}/icon_16x16@2x.png"
cp "${IMAGESET_DIR}/icon_16x16@2x.png" "${IMAGESET_DIR}/icon_32x32.png"
;;
64)
mv "${ICON_DIR}/${IMAGE_FILE_NAME}" "${IMAGESET_DIR}/icon_32x32@2x.png"
cp "${IMAGESET_DIR}/icon_32x32@2x.png" "${IMAGESET_DIR}/icon_64x64.png"
;;
128)
mv "${ICON_DIR}/${IMAGE_FILE_NAME}" "${IMAGESET_DIR}/icon_64x64@2x.png"
cp "${IMAGESET_DIR}/icon_64x64@2x.png" "${IMAGESET_DIR}/icon_128x128.png"
;;
256)
mv "${ICON_DIR}/${IMAGE_FILE_NAME}" "${IMAGESET_DIR}/icon_128x128@2x.png"
cp "${IMAGESET_DIR}/icon_128x128@2x.png" "${IMAGESET_DIR}/icon_256x256.png"
;;
512)
mv "${ICON_DIR}/${IMAGE_FILE_NAME}" "${IMAGESET_DIR}/icon_256x256@2x.png"
cp "${IMAGESET_DIR}/icon_256x256@2x.png" "${IMAGESET_DIR}/icon_512x512.png"
;;
1024)
mv "${ICON_DIR}/${IMAGE_FILE_NAME}" "${IMAGESET_DIR}/icon_512x512@2x.png"
;;
*)
echo "This image's dimensions do not fit into the needed iconset structure and will be skipped..."
esac
fi
done
ICON_FILE_COUNT=`ls -1 "${IMAGESET_DIR}" | wc -l | tr -d " "`
if [ $ICON_FILE_COUNT -gt 0 ];
then
echo "The iconset now contains $ICON_FILE_COUNT single images."
echo "Creating an icns file from the fetched printer images..."
iconutil -c icns -o "${ICNS_TMP_FILE}" "${IMAGESET_DIR}"
echo "Saving the icns file to ${DEFAULT_ICON_PATH}..."
cp "${ICNS_TMP_FILE}" "${DEFAULT_ICON_PATH}"
if [ "${ICNS_COPY_DIR}" != "" ]; then
echo "Saving a copy of the icns file to ${ICNS_COPY_DIR}/${OUTPUT_NAME}.icns..."
cp "${ICNS_TMP_FILE}" "${ICNS_COPY_DIR}/${OUTPUT_NAME}.icns"
fi
else
echo "The iconset does not contain any image files, so we will skip all other icon handling..."
fi
echo "Saving the PPD to ${PPD_OUTPUT_DIR}/${OUTPUT_NAME}.ppd..."
cp "${PPD_FILE}" "${PPD_OUTPUT_DIR}/${OUTPUT_NAME}.ppd"
echo "Removing the temporary directory..."
rm -rf "${TEMP_DIR}"
exit 0