1+ #! /usr/bin/env sh
2+ # shellcheck disable=SC2034
3+ dns_gname_info=' GNAME
4+ Site: gname.com
5+ Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_gname
6+ Options:
7+ GNAME_APPID Your APPID
8+ GNAME_APPKEY Your APPKEY
9+ OptionsAlt:
10+ '
11+
12+ GNAME_TLD_Api=" https://gname.com/request/tlds?lx=all"
13+ GNAME_Api=" https://api.gname.com"
14+ GNAME_TLDS_CACHE=" "
15+
16+ # ####### Public functions #####################
17+
18+ # Usage: add _acme-challenge.www.domain.com "T1rxqRBosdIK90xWCG3KLZNf6q_0HG9i01zxXp5CASc"
19+ dns_gname_add () {
20+ fulldomain=$1
21+ txtvalue=$( printf " %s" " $2 " | _url_encode)
22+
23+ GNAME_APPID=" ${GNAME_APPID:- $(_readaccountconf_mutable GNAME_APPID)} "
24+ GNAME_APPKEY=" ${GNAME_APPKEY:- $(_readaccountconf_mutable GNAME_APPKEY)} "
25+
26+ if [ -z " $GNAME_APPID " ] || [ -z " $GNAME_APPKEY " ]; then
27+ GNAME_APPID=" "
28+ GNAME_APPKEY=" "
29+ _err " You have not configured the APPID and APPKEY for the GNAME API."
30+ _err " You can get yours from here http://gname.com/domain/api."
31+ return 1
32+ fi
33+
34+ _saveaccountconf_mutable GNAME_APPID " $GNAME_APPID "
35+ _saveaccountconf_mutable GNAME_APPKEY " $GNAME_APPKEY "
36+
37+ if ! _extract_domain " $fulldomain " ; then
38+ _err " Failed to extract domain. Please check your network or API response."
39+ return 1
40+ fi
41+
42+ gntime=$( date +%s)
43+
44+ # If the hostname is empty, you need to replace it with @.
45+ final_hostname=$( printf " %s" " ${ext_hostname:-@ } " | _url_encode)
46+
47+ # Parameters need to be sorted by key
48+ body=" appid=$GNAME_APPID &gntime=$gntime &jlz=$txtvalue &lang=us&lx=TXT&mx=0&ttl=600&xl=0&ym=$ext_domain &zj=$final_hostname "
49+
50+ _info " Adding TXT record for $ext_domain , host: $final_hostname "
51+
52+ if _post_to_api " /api/resolution/add" " $body " ; then
53+ _info " Successfully added DNS record."
54+ return 0
55+ else
56+ if _contains " $post_response " " the same host records and record values" ; then
57+ _info " Successfully DNS record already exists."
58+ return 0
59+ fi
60+ _err " Failed to add DNS record via Gname API."
61+ return 1
62+ fi
63+ }
64+
65+ # Usage: remove _acme-challenge.www.domain.com "T1rxqRBosdIK90xWCG3KLZNf6q_0HG9i01zxXp5CASc"
66+ dns_gname_rm () {
67+ fulldomain=$1
68+ txtvalue=$2
69+
70+ GNAME_APPID=" ${GNAME_APPID:- $(_readaccountconf_mutable GNAME_APPID)} "
71+ GNAME_APPKEY=" ${GNAME_APPKEY:- $(_readaccountconf_mutable GNAME_APPKEY)} "
72+
73+ if [ -z " $GNAME_APPID " ] || [ -z " $GNAME_APPKEY " ]; then
74+ GNAME_APPID=" "
75+ GNAME_APPKEY=" "
76+ _err " You have not configured the APPID and APPKEY for the GNAME API."
77+ _err " You can get yours from here http://gname.com/domain/api."
78+ return 1
79+ fi
80+
81+ _saveaccountconf_mutable GNAME_APPID " $GNAME_APPID "
82+ _saveaccountconf_mutable GNAME_APPKEY " $GNAME_APPKEY "
83+
84+ if ! _extract_domain " $fulldomain " ; then
85+ _err " Failed to extract domain. Please check your network or API response."
86+ return 1
87+ fi
88+
89+ final_hostname=" ${ext_hostname:-@ } "
90+
91+ _debug " Query DNS record ID $ext_domain $final_hostname $txtvalue "
92+
93+ record_id=$( _get_record_id $ext_domain $final_hostname $txtvalue )
94+
95+ if [ -z " $record_id " ]; then
96+ _err " No DNS record found"
97+ return 1
98+ fi
99+
100+ _debug " DNS record ID:$record_id " ;
101+ gntime=$( date +%s)
102+ body=" appid=$GNAME_APPID &gntime=$gntime &jxid=$record_id &lang=us&ym=$ext_domain "
103+
104+ if ! _post_to_api " /api/resolution/delete" " $body " ; then
105+ _info " DNS record deletion failed"
106+ return 1
107+ fi
108+
109+ _info " DNS record deletion successful"
110+ return 0
111+ }
112+
113+ # Find the DNS record ID by hostname, record type, and record value.
114+ _get_record_id () {
115+ target_ym=" $1 "
116+ target_zjt=" $2 "
117+ target_jxz=" $3 "
118+ target_lx=" TXT"
119+
120+ GNAME_APPID=" ${GNAME_APPID:- $(_readaccountconf_mutable GNAME_APPID)} "
121+ GNAME_APPKEY=" ${GNAME_APPKEY:- $(_readaccountconf_mutable GNAME_APPKEY)} "
122+ gntime=$( date +%s)
123+ body=" appid=$GNAME_APPID &gntime=$gntime &limit=1000&lx=$target_lx &page=1&ym=$target_ym "
124+
125+ if ! _post_to_api " /api/resolution/list" " $body " ; then
126+ _err " Query and parsing records failed"
127+ return 1
128+ fi
129+
130+ clean_response=$( echo " $post_response " | tr -d ' \r' )
131+ records=$( echo " $clean_response " | sed ' s/.*"data":\[//; s/\],"count".*//; s/},/}\n/g' )
132+
133+ _debug " Cleaned Formatted Records:\n$records "
134+
135+ jxz_feature=$( printf " %s" " $target_jxz " | cut -c 1-10)
136+
137+ _debug " Searching with host: $target_zjt and feature: $jxz_feature "
138+
139+ matched_row=$( echo " $records " | grep " \" zjt\" :\" $target_zjt \" " | grep " \" jxz\" :\" $jxz_feature " )
140+
141+ _debug " Final Matched Row: $matched_row "
142+
143+ if [ -z " $matched_row " ]; then
144+ _err " Still can not find record row. Please check if host $target_zjt is correct."
145+ return 1
146+ fi
147+
148+ dns_record_id=$( echo " $matched_row " | _egrep_o " \" id\" :\" [^\" ]*\" " | head -n 1 | cut -d : -f 2 | tr -d ' "' )
149+
150+ if [ -n " $dns_record_id " ]; then
151+ _debug " Successfully found record ID: $dns_record_id "
152+ printf " %s" " $dns_record_id "
153+ return 0
154+ fi
155+
156+ return 1
157+ }
158+
159+ # Request GNAME API,post_response: Response content
160+ _post_to_api () {
161+ uri=$1
162+ body=$2
163+ url=" $GNAME_Api$uri "
164+ gntoken=$( _gntoken $body )
165+ body=" $body &gntoken=$gntoken "
166+ post_response=" $( _post " $body " " $url " " " " POST" " application/x-www-form-urlencoded" ) "
167+
168+ curl_err_code=$?
169+ if [ " $curl_err_code " != " 0" ]; then
170+ _err " POST API $url curl error:$curl_err_code "
171+ return 1
172+ fi
173+
174+ ret_code=$( echo " $post_response " | sed ' s/.*"code":\([-0-9]*\).*/\1/' )
175+ if [ " $ret_code " = " 1" ]; then
176+ return 0
177+ else
178+ ret_msg=$( echo " $post_response " | sed ' s/.*"msg":"\([^"]*\)".*/\1/' )
179+ _err " POST API $url error: [$ret_code ] $ret_msg "
180+ _debug " Full response: $post_response "
181+ return 1
182+ fi
183+ }
184+
185+ # Split the complete domain into a host and a main domain.
186+ # example, www.gname.com can be split into ext_hostname=www,ext_domain=gname.com
187+ _extract_domain () {
188+
189+ host=" $1 "
190+
191+ # Prioritize reading from the cache and reduce network caching
192+ if [ -z " $GNAME_TLDS_CACHE " ]; then
193+ GNAME_TLDS_CACHE=$( _get_suffixes_json)
194+ fi
195+
196+ if [ -z " $GNAME_TLDS_CACHE " ]; then
197+ _err " The list of domain suffixes is empty 02"
198+ return 1
199+ fi
200+
201+ main_part=$( echo " $GNAME_TLDS_CACHE " | sed ' s/.*"main":\[\([^]]*\)\].*/\1/' | tr -d ' "' | tr ' ,' ' ' )
202+ sub_part=$( echo " $GNAME_TLDS_CACHE " | sed ' s/.*"sub":\[\([^]]*\)\].*/\1/' | tr -d ' "' | tr ' ,' ' ' )
203+ suffix_list=$( echo " $main_part $sub_part " | tr -s ' ' | sed ' s/^[ ]//;s/[ ]$//' )
204+
205+ dot_count=$( echo " $host " | grep -o " \." | wc -l)
206+
207+ if [ " $dot_count " -eq 1 ]; then
208+ ext_hostname=" "
209+ ext_domain=" $host "
210+
211+ elif [ " $dot_count " -gt 1 ]; then
212+ matched_suffix=" "
213+ for suffix in $suffix_list ; do
214+ case " $host " in
215+ * " .$suffix " )
216+ if [ -z " $matched_suffix " ] || [ " ${# suffix} " -gt " ${# matched_suffix} " ]; then
217+ matched_suffix=" $suffix "
218+ fi
219+ ;;
220+ esac
221+ done
222+
223+ if [ -n " $matched_suffix " ]; then
224+ prefix=" ${host% .$matched_suffix } "
225+ main_name=" ${prefix##* .} "
226+
227+ ext_domain=" $main_name .$matched_suffix "
228+
229+ if [ " $host " = " $ext_domain " ]; then
230+ ext_hostname=" "
231+ else
232+ ext_hostname=" ${host% .$ext_domain } "
233+ fi
234+
235+ else
236+ ext_domain=$( echo " $host " | awk -F. ' {print $(NF-1)"."$NF}' )
237+ ext_hostname=$( echo " $host " | rev | cut -d. -f3- | rev)
238+ fi
239+ fi
240+ _debug " ext_hostname:$ext_hostname "
241+ _debug " ext_domain:$ext_domain "
242+ }
243+
244+ # Obtain the list of domain suffixes via API
245+ _get_suffixes_json () {
246+ _debug " GET request URL: $GNAME_TLD_Api Retrieves a list of domain suffixes."
247+
248+ response=" $( _get " $GNAME_TLD_Api " ) "
249+
250+ if [ " $? " != " 0" ]; then
251+ _err " Failed to retrieve list of domain suffixes"
252+ return 1
253+ fi
254+
255+ if [ -z " $response " ]; then
256+ _err " The list of domain suffixes is empty"
257+ return 1
258+ fi
259+
260+ if ! _contains " $response " " \" code\" :1" ; then
261+ _err " Failed to retrieve list of domain name suffixes; code is not 1"
262+ return 1
263+ fi
264+
265+ echo " $response "
266+ return 0
267+ }
268+
269+ # Generate API authentication signature
270+ _gntoken () {
271+ _debug " String to be signed:$1 "
272+ data_to_sign=" $1 "
273+ full_data=" ${data_to_sign}${GNAME_APPKEY} "
274+ hash=$( printf " %s" " $full_data " | _digest md5 hex | tr -d ' ' )
275+ hash_upper=$( printf " %s" " $hash " | tr ' a-z' ' A-Z' )
276+ _debug " Signature value: $hash_upper "
277+ printf " %s" " $hash_upper "
278+ }
0 commit comments