]> git.proxmox.com Git - proxmox-acme.git/blob - src/proxmox-acme
007c58d0e51a77784490ddd39981ae543882d9c3
[proxmox-acme.git] / src / proxmox-acme
1 #!/usr/bin/env sh
2
3 # copied from acme.sh
4 # Usage: multiline
5 _base64() {
6 [ "" ] #urgly
7 if [ "$1" ]; then
8 _debug3 "base64 multiline:'$1'"
9 ${ACME_OPENSSL_BIN:-openssl} base64 -e
10 else
11 _debug3 "base64 single line."
12 ${ACME_OPENSSL_BIN:-openssl} base64 -e | tr -d '\r\n'
13 fi
14 }
15
16 # Usage: multiline
17 _dbase64() {
18 if [ "$1" ]; then
19 ${ACME_OPENSSL_BIN:-openssl} base64 -d -A
20 else
21 ${ACME_OPENSSL_BIN:-openssl} base64 -d
22 fi
23 }
24
25 # Usage: hashalg [outputhex]
26 # Output Base64-encoded digest
27 _digest() {
28 alg="$1"
29 if [ -z "$alg" ]; then
30 _usage "Usage: _digest hashalg"
31 return 1
32 fi
33
34 outputhex="$2"
35
36 if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
37 if [ "$outputhex" ]; then
38 ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
39 else
40 ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -binary | _base64
41 fi
42 else
43 _err "$alg is not supported yet"
44 return 1
45 fi
46
47 }
48
49 _upper_case() {
50 # shellcheck disable=SC2018,SC2019
51 tr 'a-z' 'A-Z'
52 }
53
54 _lower_case() {
55 # shellcheck disable=SC2018,SC2019
56 tr 'A-Z' 'a-z'
57 }
58
59 _startswith() {
60 _str="$1"
61 _sub="$2"
62 echo "$_str" | grep "^$_sub" >/dev/null 2>&1
63 }
64
65 _endswith() {
66 _str="$1"
67 _sub="$2"
68 echo "$_str" | grep -- "$_sub\$" >/dev/null 2>&1
69 }
70
71 _contains() {
72 _str="$1"
73 _sub="$2"
74 echo "$_str" | grep -- "$_sub" >/dev/null 2>&1
75 }
76
77 # str index [sep]
78 _getfield() {
79 _str="$1"
80 _findex="$2"
81 _sep="$3"
82
83 if [ -z "$_findex" ]; then
84 _usage "Usage: str field [sep]"
85 return 1
86 fi
87
88 if [ -z "$_sep" ]; then
89 _sep=","
90 fi
91
92 _ffi="$_findex"
93 while [ "$_ffi" -gt "0" ]; do
94 _fv="$(echo "$_str" | cut -d "$_sep" -f "$_ffi")"
95 if [ "$_fv" ]; then
96 printf -- "%s" "$_fv"
97 return 0
98 fi
99 _ffi="$(_math "$_ffi" - 1)"
100 done
101
102 printf -- "%s" "$_str"
103
104 }
105
106 _exists() {
107 cmd="$1"
108 if [ -z "$cmd" ]; then
109 _usage "Usage: _exists cmd"
110 return 1
111 fi
112
113 if eval type type >/dev/null 2>&1; then
114 eval type "$cmd" >/dev/null 2>&1
115 elif command >/dev/null 2>&1; then
116 command -v "$cmd" >/dev/null 2>&1
117 else
118 which "$cmd" >/dev/null 2>&1
119 fi
120 ret="$?"
121 _debug3 "$cmd exists=$ret"
122 return $ret
123 }
124
125 # a + b
126 _math() {
127 _m_opts="$@"
128 printf "%s" "$(($_m_opts))"
129 }
130
131 _egrep_o() {
132 if ! egrep -o "$1" 2>/dev/null; then
133 sed -n 's/.*\('"$1"'\).*/\1/p'
134 fi
135 }
136
137 _inithttp() {
138
139 if [ -z "$HTTP_HEADER" ] || ! touch "$HTTP_HEADER"; then
140 HTTP_HEADER="$(_mktemp)"
141 _debug2 HTTP_HEADER "$HTTP_HEADER"
142 fi
143
144 if [ "$__HTTP_INITIALIZED" ]; then
145 if [ "$_ACME_CURL$_ACME_WGET" ]; then
146 _debug2 "Http already initialized."
147 return 0
148 fi
149 fi
150
151 if [ -z "$_ACME_CURL" ] && _exists "curl"; then
152 _ACME_CURL="curl -L --silent --dump-header $HTTP_HEADER "
153 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
154 _CURL_DUMP="$(_mktemp)"
155 _ACME_CURL="$_ACME_CURL --trace-ascii $_CURL_DUMP "
156 fi
157
158 if [ "$CA_PATH" ]; then
159 _ACME_CURL="$_ACME_CURL --capath $CA_PATH "
160 elif [ "$CA_BUNDLE" ]; then
161 _ACME_CURL="$_ACME_CURL --cacert $CA_BUNDLE "
162 fi
163
164 if _contains "$(curl --help 2>&1)" "--globoff"; then
165 _ACME_CURL="$_ACME_CURL -g "
166 fi
167 fi
168
169 if [ -z "$_ACME_WGET" ] && _exists "wget"; then
170 _ACME_WGET="wget -q"
171 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
172 _ACME_WGET="$_ACME_WGET -d "
173 fi
174 if [ "$CA_PATH" ]; then
175 _ACME_WGET="$_ACME_WGET --ca-directory=$CA_PATH "
176 elif [ "$CA_BUNDLE" ]; then
177 _ACME_WGET="$_ACME_WGET --ca-certificate=$CA_BUNDLE "
178 fi
179 fi
180
181 #from wget 1.14: do not skip body on 404 error
182 if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help 2>&1)" "--content-on-error"; then
183 _ACME_WGET="$_ACME_WGET --content-on-error "
184 fi
185
186 __HTTP_INITIALIZED=1
187
188 }
189
190 # body url [needbase64] [POST|PUT|DELETE] [ContentType]
191 _post() {
192 body="$1"
193 _post_url="$2"
194 needbase64="$3"
195 httpmethod="$4"
196 _postContentType="$5"
197
198 if [ -z "$httpmethod" ]; then
199 httpmethod="POST"
200 fi
201 _debug $httpmethod
202 _debug "_post_url" "$_post_url"
203 _debug2 "body" "$body"
204 _debug2 "_postContentType" "$_postContentType"
205
206 _inithttp
207
208 if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
209 _CURL="$_ACME_CURL"
210 if [ "$HTTPS_INSECURE" ]; then
211 _CURL="$_CURL --insecure "
212 fi
213 if [ "$httpmethod" = "HEAD" ]; then
214 _CURL="$_CURL -I "
215 fi
216 _debug "_CURL" "$_CURL"
217 if [ "$needbase64" ]; then
218 if [ "$body" ]; then
219 if [ "$_postContentType" ]; then
220 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
221 else
222 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
223 fi
224 else
225 if [ "$_postContentType" ]; then
226 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url" | _base64)"
227 else
228 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url" | _base64)"
229 fi
230 fi
231 else
232 if [ "$body" ]; then
233 if [ "$_postContentType" ]; then
234 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
235 else
236 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
237 fi
238 else
239 if [ "$_postContentType" ]; then
240 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url")"
241 else
242 response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$_post_url")"
243 fi
244 fi
245 fi
246 _ret="$?"
247 if [ "$_ret" != "0" ]; then
248 _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $_ret"
249 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
250 _err "Here is the curl dump log:"
251 _err "$(cat "$_CURL_DUMP")"
252 fi
253 fi
254 elif [ "$_ACME_WGET" ]; then
255 _WGET="$_ACME_WGET"
256 if [ "$HTTPS_INSECURE" ]; then
257 _WGET="$_WGET --no-check-certificate "
258 fi
259 if [ "$httpmethod" = "HEAD" ]; then
260 _WGET="$_WGET --read-timeout=3.0 --tries=2 "
261 fi
262 _debug "_WGET" "$_WGET"
263 if [ "$needbase64" ]; then
264 if [ "$httpmethod" = "POST" ]; then
265 if [ "$_postContentType" ]; then
266 response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
267 else
268 response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
269 fi
270 else
271 if [ "$_postContentType" ]; then
272 response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
273 else
274 response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER" | _base64)"
275 fi
276 fi
277 else
278 if [ "$httpmethod" = "POST" ]; then
279 if [ "$_postContentType" ]; then
280 response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
281 else
282 response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
283 fi
284 elif [ "$httpmethod" = "HEAD" ]; then
285 if [ "$_postContentType" ]; then
286 response="$($_WGET --spider -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
287 else
288 response="$($_WGET --spider -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --post-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
289 fi
290 else
291 if [ "$_postContentType" ]; then
292 response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --header "Content-Type: $_postContentType" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
293 else
294 response="$($_WGET -S -O - --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" --method $httpmethod --body-data="$body" "$_post_url" 2>"$HTTP_HEADER")"
295 fi
296 fi
297 fi
298 _ret="$?"
299 if [ "$_ret" = "8" ]; then
300 _ret=0
301 _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
302 fi
303 if [ "$_ret" != "0" ]; then
304 _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $_ret"
305 fi
306 _sed_i "s/^ *//g" "$HTTP_HEADER"
307 else
308 _ret="$?"
309 _err "Neither curl nor wget is found, can not do $httpmethod."
310 fi
311 _debug "_ret" "$_ret"
312 printf "%s" "$response"
313 return $_ret
314 }
315
316 # url getheader timeout
317 _get() {
318 _debug GET
319 url="$1"
320 onlyheader="$2"
321 t="$3"
322 _debug url "$url"
323 _debug "timeout=$t"
324
325 _inithttp
326
327 if [ "$_ACME_CURL" ] && [ "${ACME_USE_WGET:-0}" = "0" ]; then
328 _CURL="$_ACME_CURL"
329 if [ "$HTTPS_INSECURE" ]; then
330 _CURL="$_CURL --insecure "
331 fi
332 if [ "$t" ]; then
333 _CURL="$_CURL --connect-timeout $t"
334 fi
335 _debug "_CURL" "$_CURL"
336 if [ "$onlyheader" ]; then
337 $_CURL -I --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
338 else
339 $_CURL --user-agent "$USER_AGENT" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" "$url"
340 fi
341 ret=$?
342 if [ "$ret" != "0" ]; then
343 _err "Please refer to https://curl.haxx.se/libcurl/c/libcurl-errors.html for error code: $ret"
344 if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
345 _err "Here is the curl dump log:"
346 _err "$(cat "$_CURL_DUMP")"
347 fi
348 fi
349 elif [ "$_ACME_WGET" ]; then
350 _WGET="$_ACME_WGET"
351 if [ "$HTTPS_INSECURE" ]; then
352 _WGET="$_WGET --no-check-certificate "
353 fi
354 if [ "$t" ]; then
355 _WGET="$_WGET --timeout=$t"
356 fi
357 _debug "_WGET" "$_WGET"
358 if [ "$onlyheader" ]; then
359 $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -S -O /dev/null "$url" 2>&1 | sed 's/^[ ]*//g'
360 else
361 $_WGET --user-agent="$USER_AGENT" --header "$_H5" --header "$_H4" --header "$_H3" --header "$_H2" --header "$_H1" -O - "$url"
362 fi
363 ret=$?
364 if [ "$ret" = "8" ]; then
365 ret=0
366 _debug "wget returns 8, the server returns a 'Bad request' response, lets process the response later."
367 fi
368 if [ "$ret" != "0" ]; then
369 _err "Please refer to https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html for error code: $ret"
370 fi
371 else
372 ret=$?
373 _err "Neither curl nor wget is found, can not do GET."
374 fi
375 _debug "ret" "$ret"
376 return $ret
377 }
378
379 _head_n() {
380 head -n "$1"
381 }
382
383 _tail_n() {
384 if ! tail -n "$1" 2>/dev/null; then
385 #fix for solaris
386 tail -"$1"
387 fi
388 }
389
390 # stdin output hexstr splited by one space
391 # input:"abc"
392 # output: " 61 62 63"
393 _hex_dump() {
394 if _exists od; then
395 od -A n -v -t x1 | tr -s " " | sed 's/ $//' | tr -d "\r\t\n"
396 elif _exists hexdump; then
397 _debug3 "using hexdump"
398 hexdump -v -e '/1 ""' -e '/1 " %02x" ""'
399 elif _exists xxd; then
400 _debug3 "using xxd"
401 xxd -ps -c 20 -i | sed "s/ 0x/ /g" | tr -d ",\n" | tr -s " "
402 else
403 _debug3 "using _ascii_hex"
404 str=$(cat)
405 _ascii_hex "$str"
406 fi
407 }
408
409 # stdin stdout
410 _url_encode() {
411 _hex_str=$(_hex_dump)
412 _debug3 "_url_encode"
413 _debug3 "_hex_str" "$_hex_str"
414 for _hex_code in $_hex_str; do
415 #upper case
416 case "${_hex_code}" in
417 "41")
418 printf "%s" "A"
419 ;;
420 "42")
421 printf "%s" "B"
422 ;;
423 "43")
424 printf "%s" "C"
425 ;;
426 "44")
427 printf "%s" "D"
428 ;;
429 "45")
430 printf "%s" "E"
431 ;;
432 "46")
433 printf "%s" "F"
434 ;;
435 "47")
436 printf "%s" "G"
437 ;;
438 "48")
439 printf "%s" "H"
440 ;;
441 "49")
442 printf "%s" "I"
443 ;;
444 "4a")
445 printf "%s" "J"
446 ;;
447 "4b")
448 printf "%s" "K"
449 ;;
450 "4c")
451 printf "%s" "L"
452 ;;
453 "4d")
454 printf "%s" "M"
455 ;;
456 "4e")
457 printf "%s" "N"
458 ;;
459 "4f")
460 printf "%s" "O"
461 ;;
462 "50")
463 printf "%s" "P"
464 ;;
465 "51")
466 printf "%s" "Q"
467 ;;
468 "52")
469 printf "%s" "R"
470 ;;
471 "53")
472 printf "%s" "S"
473 ;;
474 "54")
475 printf "%s" "T"
476 ;;
477 "55")
478 printf "%s" "U"
479 ;;
480 "56")
481 printf "%s" "V"
482 ;;
483 "57")
484 printf "%s" "W"
485 ;;
486 "58")
487 printf "%s" "X"
488 ;;
489 "59")
490 printf "%s" "Y"
491 ;;
492 "5a")
493 printf "%s" "Z"
494 ;;
495
496 #lower case
497 "61")
498 printf "%s" "a"
499 ;;
500 "62")
501 printf "%s" "b"
502 ;;
503 "63")
504 printf "%s" "c"
505 ;;
506 "64")
507 printf "%s" "d"
508 ;;
509 "65")
510 printf "%s" "e"
511 ;;
512 "66")
513 printf "%s" "f"
514 ;;
515 "67")
516 printf "%s" "g"
517 ;;
518 "68")
519 printf "%s" "h"
520 ;;
521 "69")
522 printf "%s" "i"
523 ;;
524 "6a")
525 printf "%s" "j"
526 ;;
527 "6b")
528 printf "%s" "k"
529 ;;
530 "6c")
531 printf "%s" "l"
532 ;;
533 "6d")
534 printf "%s" "m"
535 ;;
536 "6e")
537 printf "%s" "n"
538 ;;
539 "6f")
540 printf "%s" "o"
541 ;;
542 "70")
543 printf "%s" "p"
544 ;;
545 "71")
546 printf "%s" "q"
547 ;;
548 "72")
549 printf "%s" "r"
550 ;;
551 "73")
552 printf "%s" "s"
553 ;;
554 "74")
555 printf "%s" "t"
556 ;;
557 "75")
558 printf "%s" "u"
559 ;;
560 "76")
561 printf "%s" "v"
562 ;;
563 "77")
564 printf "%s" "w"
565 ;;
566 "78")
567 printf "%s" "x"
568 ;;
569 "79")
570 printf "%s" "y"
571 ;;
572 "7a")
573 printf "%s" "z"
574 ;;
575 #numbers
576 "30")
577 printf "%s" "0"
578 ;;
579 "31")
580 printf "%s" "1"
581 ;;
582 "32")
583 printf "%s" "2"
584 ;;
585 "33")
586 printf "%s" "3"
587 ;;
588 "34")
589 printf "%s" "4"
590 ;;
591 "35")
592 printf "%s" "5"
593 ;;
594 "36")
595 printf "%s" "6"
596 ;;
597 "37")
598 printf "%s" "7"
599 ;;
600 "38")
601 printf "%s" "8"
602 ;;
603 "39")
604 printf "%s" "9"
605 ;;
606 "2d")
607 printf "%s" "-"
608 ;;
609 "5f")
610 printf "%s" "_"
611 ;;
612 "2e")
613 printf "%s" "."
614 ;;
615 "7e")
616 printf "%s" "~"
617 ;;
618 #other hex
619 *)
620 printf '%%%s' "$_hex_code"
621 ;;
622 esac
623 done
624 }
625
626 # Usage: hashalg secret_hex [outputhex]
627 # Output binary hmac
628 _hmac() {
629 alg="$1"
630 secret_hex="$2"
631 outputhex="$3"
632
633 if [ -z "$secret_hex" ]; then
634 _usage "Usage: _hmac hashalg secret [outputhex]"
635 return 1
636 fi
637
638 if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ]; then
639 if [ "$outputhex" ]; then
640 (${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" 2>/dev/null || ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)") | cut -d = -f 2 | tr -d ' '
641 else
642 ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -mac HMAC -macopt "hexkey:$secret_hex" -binary 2>/dev/null || ${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hmac "$(printf "%s" "$secret_hex" | _h2b)" -binary
643 fi
644 else
645 _err "$alg is not supported yet"
646 return 1
647 fi
648
649 }
650
651 # domain
652 _is_idn() {
653 _is_idn_d="$1"
654 _debug2 _is_idn_d "$_is_idn_d"
655 _idn_temp=$(printf "%s" "$_is_idn_d" | tr -d '0-9' | tr -d 'a-z' | tr -d 'A-Z' | tr -d '*.,-_')
656 _debug2 _idn_temp "$_idn_temp"
657 [ "$_idn_temp" ]
658 }
659
660 # aa.com
661 # aa.com,bb.com,cc.com
662 _idn() {
663 __idn_d="$1"
664 if ! _is_idn "$__idn_d"; then
665 printf "%s" "$__idn_d"
666 return 0
667 fi
668
669 if _exists idn; then
670 if _contains "$__idn_d" ','; then
671 _i_first="1"
672 for f in $(echo "$__idn_d" | tr ',' ' '); do
673 [ -z "$f" ] && continue
674 if [ -z "$_i_first" ]; then
675 printf "%s" ","
676 else
677 _i_first=""
678 fi
679 idn --quiet "$f" | tr -d "\r\n"
680 done
681 else
682 idn "$__idn_d" | tr -d "\r\n"
683 fi
684 else
685 _err "Please install idn to process IDN names."
686 fi
687 }
688
689 _normalizeJson() {
690 sed "s/\" *: *\([\"{\[]\)/\":\1/g" | sed "s/^ *\([^ ]\)/\1/" | tr -d "\r\n"
691 }
692
693 # options file
694 _sed_i() {
695 options="$1"
696 filename="$2"
697 if [ -z "$filename" ]; then
698 _usage "Usage:_sed_i options filename"
699 return 1
700 fi
701 _debug2 options "$options"
702 if sed -h 2>&1 | grep "\-i\[SUFFIX]" >/dev/null 2>&1; then
703 _debug "Using sed -i"
704 sed -i "$options" "$filename"
705 else
706 _debug "No -i support in sed"
707 text="$(cat "$filename")"
708 echo "$text" | sed "$options" >"$filename"
709 fi
710 }
711
712 # sleep sec
713 _sleep() {
714 _sleep_sec="$1"
715 if [ "$__INTERACTIVE" ]; then
716 _sleep_c="$_sleep_sec"
717 while [ "$_sleep_c" -ge "0" ]; do
718 printf "\r \r"
719 __green "$_sleep_c"
720 _sleep_c="$(_math "$_sleep_c" - 1)"
721 sleep 1
722 done
723 printf "\r"
724 else
725 sleep "$_sleep_sec"
726 fi
727 }
728
729 _stat() {
730 #Linux
731 if stat -c '%U:%G' "$1" 2>/dev/null; then
732 return
733 fi
734
735 #BSD
736 if stat -f '%Su:%Sg' "$1" 2>/dev/null; then
737 return
738 fi
739
740 return 1 #error, 'stat' not found
741 }
742
743
744 _time() {
745 date -u "+%s"
746 }
747
748 _utc_date() {
749 date -u "+%Y-%m-%d %H:%M:%S"
750 }
751
752 # stubbed/aliased:
753 __green() {
754 if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then
755 printf '\033[1;31;32m%b\033[0m' "$1"
756 return
757 fi
758 printf -- "%b" "$1"
759 }
760
761 __red() {
762 if [ "${__INTERACTIVE}${ACME_NO_COLOR:-0}" = "10" -o "${ACME_FORCE_COLOR}" = "1" ]; then
763 printf '\033[1;31;40m%b\033[0m' "$1"
764 return
765 fi
766 printf -- "%b" "$1"
767 }
768
769 _log() {
770 [ -z "$LOG_FILE" ] && return
771 _printargs "$@" >>"$LOG_FILE"
772 }
773
774 _info() {
775 _log "$@"
776 if [ "${SYS_LOG:-$SYSLOG_LEVEL_NONE}" -ge "$SYSLOG_LEVEL_INFO" ]; then
777 _syslog "$SYSLOG_INFO" "$@"
778 fi
779 _printargs "$@"
780 }
781
782 _err() {
783 _syslog "$SYSLOG_ERROR" "$@"
784 _log "$@"
785 if [ -z "$NO_TIMESTAMP" ] || [ "$NO_TIMESTAMP" = "0" ]; then
786 printf -- "%s" "[$(date)] " >&2
787 fi
788 if [ -z "$2" ]; then
789 __red "$1" >&2
790 else
791 __red "$1='$2'" >&2
792 fi
793 printf "\n" >&2
794 return 1
795 }
796
797 # key
798 _readaccountconf() {
799 _read_conf "$ACCOUNT_CONF_PATH" "$1"
800 }
801
802 # key
803 _readaccountconf_mutable() {
804 _rac_key="$1"
805 _readaccountconf "SAVED_$_rac_key"
806 }