From 2a71070c43b7a5406512f30a9c71f413ad264c6b Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Mon, 5 Jun 2023 22:23:26 +0300 Subject: [PATCH] luci-app-acme: DNS API specific fields The credentials edition is not user friendy. We need a separate fields for each param. Signed-off-by: Sergey Ponomarev --- .../htdocs/luci-static/resources/view/acme.js | 420 ++++++++++++------ 1 file changed, 280 insertions(+), 140 deletions(-) diff --git a/applications/luci-app-acme/htdocs/luci-static/resources/view/acme.js b/applications/luci-app-acme/htdocs/luci-static/resources/view/acme.js index eea5ec643abe..7d2a77ee0da0 100644 --- a/applications/luci-app-acme/htdocs/luci-static/resources/view/acme.js +++ b/applications/luci-app-acme/htdocs/luci-static/resources/view/acme.js @@ -75,149 +75,248 @@ return view.extend({ o.depends("validation_method", "dns"); // List of supported DNS API. Names are same as file names in acme.sh for easier search. // May be outdated but not changed too often. - o.value("dns_1984hosting", "1984hosting"); - o.value("dns_acmedns", "acmedns"); - o.value("dns_acmeproxy", "acmeproxy"); - o.value("dns_active24", "active24"); - o.value("dns_ad", "ad"); - o.value("dns_ali", "ali"); - o.value("dns_anx", "anx"); - o.value("dns_arvan", "arvan"); - o.value("dns_aurora", "aurora"); - o.value("dns_autodns", "autodns"); - o.value("dns_aws", "aws"); - o.value("dns_azion", "azion"); - o.value("dns_azure", "azure"); - o.value("dns_bunny", "bunny"); - o.value("dns_cf", "cf"); - o.value("dns_clouddns", "clouddns"); - o.value("dns_cloudns", "cloudns"); - o.value("dns_cn", "cn"); - o.value("dns_conoha", "conoha"); - o.value("dns_constellix", "constellix"); - o.value("dns_cpanel", "cpanel"); - o.value("dns_curanet", "curanet"); - o.value("dns_cyon", "cyon"); - o.value("dns_da", "da"); - o.value("dns_ddnss", "ddnss"); - o.value("dns_desec", "desec"); - o.value("dns_df", "df"); - o.value("dns_dgon", "dgon"); - o.value("dns_dnshome", "dnshome"); - o.value("dns_dnsimple", "dnsimple"); - o.value("dns_dnsservices", "dnsservices"); - o.value("dns_do", "do"); - o.value("dns_doapi", "doapi"); - o.value("dns_domeneshop", "domeneshop"); - o.value("dns_dp", "dp"); - o.value("dns_dpi", "dpi"); - o.value("dns_dreamhost", "dreamhost"); - o.value("dns_duckdns", "duckdns"); - o.value("dns_durabledns", "durabledns"); - o.value("dns_dyn", "dyn"); - o.value("dns_dynu", "dynu"); - o.value("dns_dynv6", "dynv6"); - o.value("dns_easydns", "easydns"); - o.value("dns_edgedns", "edgedns"); - o.value("dns_euserv", "euserv"); - o.value("dns_exoscale", "exoscale"); - o.value("dns_fornex", "fornex"); - o.value("dns_freedns", "freedns"); - o.value("dns_gandi_livedns", "gandi_livedns"); - o.value("dns_gcloud", "gcloud"); - o.value("dns_gcore", "gcore"); - o.value("dns_gd", "gd"); - o.value("dns_geoscaling", "geoscaling"); - o.value("dns_googledomains", "googledomains"); - o.value("dns_he", "he"); - o.value("dns_hetzner", "hetzner"); - o.value("dns_hexonet", "hexonet"); - o.value("dns_hostingde", "hostingde"); - o.value("dns_huaweicloud", "huaweicloud"); - o.value("dns_infoblox", "infoblox"); - o.value("dns_infomaniak", "infomaniak"); - o.value("dns_internetbs", "internetbs"); - o.value("dns_inwx", "inwx"); - o.value("dns_ionos", "ionos"); - o.value("dns_ipv64", "ipv64"); - o.value("dns_ispconfig", "ispconfig"); - o.value("dns_jd", "jd"); - o.value("dns_joker", "joker"); - o.value("dns_kappernet", "kappernet"); - o.value("dns_kas", "kas"); - o.value("dns_kinghost", "kinghost"); - o.value("dns_la", "la"); - o.value("dns_leaseweb", "leaseweb"); - o.value("dns_lexicon", "lexicon"); - o.value("dns_linode", "linode"); - o.value("dns_linode_v4", "linode_v4"); - o.value("dns_loopia", "loopia"); - o.value("dns_lua", "lua"); - o.value("dns_maradns", "maradns"); - o.value("dns_me", "me"); - o.value("dns_miab", "miab"); - o.value("dns_misaka", "misaka"); - o.value("dns_myapi", "myapi"); - o.value("dns_mydevil", "mydevil"); - o.value("dns_mydnsjp", "mydnsjp"); - o.value("dns_mythic_beasts", "mythic_beasts"); - o.value("dns_namecheap", "namecheap"); - o.value("dns_namecom", "namecom"); - o.value("dns_namesilo", "namesilo"); - o.value("dns_nanelo", "nanelo"); - o.value("dns_nederhost", "nederhost"); - o.value("dns_neodigit", "neodigit"); - o.value("dns_netcup", "netcup"); - o.value("dns_netlify", "netlify"); - o.value("dns_nic", "nic"); - o.value("dns_njalla", "njalla"); - o.value("dns_nm", "nm"); - o.value("dns_nsd", "nsd"); - o.value("dns_nsone", "nsone"); - o.value("dns_nsupdate", "nsupdate"); - o.value("dns_nw", "nw"); - o.value("dns_oci", "oci"); - o.value("dns_one", "one"); - o.value("dns_online", "online"); - o.value("dns_openprovider", "openprovider"); - o.value("dns_openstack", "openstack"); - o.value("dns_opnsense", "opnsense"); - o.value("dns_ovh", "ovh"); - o.value("dns_pdns", "pdns"); - o.value("dns_pleskxml", "pleskxml"); - o.value("dns_pointhq", "pointhq"); - o.value("dns_porkbun", "porkbun"); - o.value("dns_rackcorp", "rackcorp"); - o.value("dns_rackspace", "rackspace"); - o.value("dns_rage4", "rage4"); - o.value("dns_rcode0", "rcode0"); - o.value("dns_regru", "regru"); - o.value("dns_scaleway", "scaleway"); - o.value("dns_schlundtech", "schlundtech"); - o.value("dns_selectel", "selectel"); - o.value("dns_selfhost", "selfhost"); - o.value("dns_servercow", "servercow"); - o.value("dns_simply", "simply"); - o.value("dns_tele3", "tele3"); - o.value("dns_transip", "transip"); - o.value("dns_udr", "udr"); - o.value("dns_ultra", "ultra"); - o.value("dns_unoeuro", "unoeuro"); - o.value("dns_variomedia", "variomedia"); - o.value("dns_veesp", "veesp"); - o.value("dns_vercel", "vercel"); - o.value("dns_vscale", "vscale"); - o.value("dns_vultr", "vultr"); - o.value("dns_websupport", "websupport"); - o.value("dns_world4you", "world4you"); - o.value("dns_yandex", "yandex"); - o.value("dns_yc", "yc"); - o.value("dns_zilore", "zilore"); - o.value("dns_zone", "zone"); - o.value("dns_zonomi", "zonomi"); + o.value("dns_1984hosting", "1984.is"); + o.value("dns_acmedns", "ACME DNS API"); + o.value("dns_acmeproxy", "ACME Proxy github.com/mdbraber/acmeproxy"); + o.value("dns_active24", "Active24.com"); + o.value("dns_ad", "Alwaysdata.com"); + o.value("dns_ali", "Alibaba Cloud Aliyun.com"); + o.value("dns_anx", "Anexia.com"); + o.value("dns_arvan", "ArvanCloud.ir"); + o.value("dns_aurora", "AuroraDNS.eu"); + o.value("dns_autodns", "autoDNS (InternetX)"); + o.value("dns_aws", "Amazon AWS Route53"); + o.value("dns_azion", "Azion.com"); + o.value("dns_azure", "Azure"); + o.value("dns_bunny", "Bunny.net"); + o.value("dns_cf", "CloudFlare.com"); + o.value("dns_clouddns", "CloudDNS vshosting.cz"); + o.value("dns_cloudns", "ClouDNS.net"); + o.value("dns_cn", "Core-Networks.de"); + o.value("dns_conoha", "ConoHa.io"); + o.value("dns_constellix", "constellix.com"); + o.value("dns_cpanel", "CPanel"); + o.value("dns_curanet", "curanet.dk scannet.dk wannafind.dk dandomain.dk"); + o.value("dns_cyon", "cayon.ch"); + o.value("dns_da", "DirectAdmin.com"); + o.value("dns_ddnss", "DDNSS.de"); + o.value("dns_desec", "deSEC.io"); + o.value("dns_df", "DynDnsFree.de"); + o.value("dns_dgon", "DigitalOcean.com"); + o.value("dns_dnshome", "dnsHome.de"); + o.value("dns_dnsimple", "DNSimple.com"); + o.value("dns_dnsservices", "dns.services"); + o.value("dns_doapi", "Domain-Offensive do.de"); + o.value("dns_domeneshop", "DomeneShop.no"); + o.value("dns_dp", "DNSPod.cn"); + // o.value("dns_dpi", "DNSPod.com"); + o.value("dns_dreamhost", "DreamHost.com"); + o.value("dns_duckdns", "DuckDNS.org"); + o.value("dns_durabledns", "DurableDNS.com"); + o.value("dns_dyn", "Dyn.com"); + o.value("dns_dynu", "Dynu.com"); + o.value("dns_dynv6", "DynV6.com"); + o.value("dns_easydns", "EasyDNS.net"); + o.value("dns_edgedns", "Akamai Edge DNS"); + o.value("dns_euserv", "euserv.eu"); + o.value("dns_exoscale", "Exoscale.com"); + o.value("dns_fornex", "fornex.com"); + o.value("dns_freedns", "FreeDNS.afraid.org"); + o.value("dns_gandi_livedns", "LiveDNS.Gandi.net"); + // o.value("dns_gcloud", "Google Cloud gcloud client"); + o.value("dns_gcore", "Gcore.com"); + o.value("dns_gd", "GoDaddy.com"); + o.value("dns_geoscaling", "Geoscaling.com"); + o.value("dns_googledomains", "Google Domains"); + o.value("dns_he", "he.net"); + o.value("dns_hetzner", "Hetzner.com"); + o.value("dns_hexonet", "Hexonet.net"); + o.value("dns_hostingde", "Hosting.de"); + o.value("dns_huaweicloud", "MyHuaweiCloud.com"); + o.value("dns_infoblox", "Infoblox"); + o.value("dns_infomaniak", "InfoManiak.com"); + o.value("dns_internetbs", "InternetBS.net"); + o.value("dns_inwx", "inwx.de"); + o.value("dns_ionos", "IONOS.com"); + o.value("dns_ipv64", "ipv64.net"); + o.value("dns_ispconfig", "ISPConfig Server"); + o.value("dns_jd", "JDCloud.com"); + o.value("dns_joker", "Joker.com"); + o.value("dns_kappernet", "kapper.net"); + o.value("dns_kas", "kasserver.com"); + o.value("dns_kinghost", "KingHost.net"); + o.value("dns_la", "dns.la"); + o.value("dns_leaseweb", "leaseweb.com"); + // o.value("dns_lexicon", "Lexicon client"); + o.value("dns_linode_v4", "Linode.com"); + o.value("dns_loopia", "Loopia.se"); + o.value("dns_lua", "LuaDNS.com"); + // o.value("dns_maradns", "MaraDNS Server zone file"); + o.value("dns_me", "DNSMadeEasy.com"); + // o.value("dns_miab", "Mail-in-a-Box Server API"); + o.value("dns_misaka", "misaka.io"); + o.value("dns_mydevil", "MyDevil.net"); + o.value("dns_mydnsjp", "MyDNS.JP"); + o.value("dns_mythic_beasts", "Mythic-Beasts.com"); + o.value("dns_namecheap", "NameCheap.com"); + o.value("dns_namecom", "Name.com"); + o.value("dns_namesilo", "NameSilo.com"); + o.value("dns_nanelo", "Nanelo.com"); + o.value("dns_nederhost", "NederHost.nl"); + o.value("dns_neodigit", "Neodigit.net"); + o.value("dns_netcup", "netcup.eu netcup.de"); + o.value("dns_netlify", "Netlify.com"); + o.value("dns_nic", "nic.ru"); + o.value("dns_njalla", "Njalla njal.la"); + o.value("dns_nm", "NameMaster.de"); + // o.value("dns_nsd", "NSD Server zone file"); + o.value("dns_nsone", "NS1 nsone.net"); + o.value("dns_nsupdate", "nsupdate (RFC2136) Server"); + o.value("dns_nw", "Nexcess.net"); + o.value("dns_oci", "Oracle Cloud Infrastructure (OCI)"); + o.value("dns_one", "one.com"); + o.value("dns_online", "online.net"); + o.value("dns_openprovider", "OpenProvider.com"); + // o.value("dns_openstack", "OpenStack Client"); + o.value("dns_opnsense", "OPNsense Bind API"); + o.value("dns_ovh", "OVH ovh.com ovhcloud.com kimsufi.com soyoustart.com"); + o.value("dns_pdns", "PowerDNS Server"); + o.value("dns_pleskxml", "plesk.com XML API"); + o.value("dns_pointhq", "PoinDNS pointhq.com"); + o.value("dns_porkbun", "Porkbun.com"); + o.value("dns_rackcorp", "RackCorp.com"); + o.value("dns_rackspace", "RackSpace rackspacecloud.com"); + o.value("dns_rage4", "rage4.com"); + o.value("dns_rcode0", "Rcode0 rcodezero.at"); + o.value("dns_regru", "Reg.ru"); + o.value("dns_scaleway", "Scaleway.com"); + o.value("dns_schlundtech", "Schlundtech.de"); + o.value("dns_selectel", "Selectel.ru"); + o.value("dns_selfhost", "selfhost.de"); + o.value("dns_servercow", "servercow.de"); + o.value("dns_simply", "Simply.com"); + o.value("dns_tele3", "tele3.cz"); + o.value("dns_transip", "transip.nl"); + o.value("dns_udr", "ud-reselling.com"); + o.value("dns_ultra", "UltraDNS.com"); + o.value("dns_variomedia", "variomedia.de"); + o.value("dns_veesp", "veesp.com"); + o.value("dns_vercel", "Vercel.com"); + o.value("dns_vscale", "vscale.io"); + o.value("dns_vultr", "vultr.com"); + o.value("dns_websupport", "websupport.sk"); + o.value("dns_world4you", "World4You.com"); + o.value("dns_yandex", "Yandex DNS dns.yandex.ru"); + o.value("dns_yc", "Yandex Cloud cloud.yandex.net"); + o.value("dns_zilore", "zilore.com"); + o.value("dns_zone", "Zone.ee"); + o.value("dns_zonomi", "Zonomi.com"); o.default = "dns_duckdns"; // The most popular DDNS o.modalonly = true; + o = _addDnsCredentialField(s, "dns_1984hosting", "One984HOSTING_Username", "1984.is Username", ""); + o = _addDnsCredentialField(s, "dns_1984hosting", "One984HOSTING_Password", "1984.is Password", ""); + + o = _addDnsCredentialField(s, "dns_acmedns", "ACMEDNS_BASE_URL", "ACMEDNS URL", ""); + o = _addDnsCredentialField(s, "dns_acmedns", "ACMEDNS_USERNAME", "ACMEDNS User", ""); + o = _addDnsCredentialField(s, "dns_acmedns", "ACMEDNS_PASSWORD", "ACMEDNS Password", ""); + o = _addDnsCredentialField(s, "dns_acmedns", "ACMEDNS_SUBDOMAIN", "ACMEDNS Subdomain", ""); + + o = _addDnsCredentialField(s, "dns_ali", "Ali_Key", "Ali Key", ""); + o = _addDnsCredentialField(s, "dns_ali", "Ali_Secret", "Ali Secret", ""); + + o = _addDnsCredentialField(s, "dns_aws", "AWS_ACCESS_KEY_ID", "AWS access key id", ""); + o = _addDnsCredentialField(s, "dns_aws", "AWS_SECRET_ACCESS_KEY", "AWS secret access key", ""); + + o = _addDnsCredentialField(s, "dns_bunny", "BUNNY_API_KEY", "Bunny API Key", ""); + + o = _addDnsCredentialField(s, "dns_cf", "CF_Key", "CF Key", ""); + o = _addDnsCredentialField(s, "dns_cf", "CF_Email", "CF Email", ""); + o = _addDnsCredentialField(s, "dns_cf", "CF_Token", "CF Token", ""); + o = _addDnsCredentialField(s, "dns_cf", "CF_Account_ID", "CF Account ID", ""); + o = _addDnsCredentialField(s, "dns_cf", "CF_Zone_ID", "CF Zone ID", ""); + + o = _addDnsCredentialField(s, "dns_duckdns", "DuckDNS_Token", "DuckDNS Token", "Open DuckDNS and copy a token here"); + + o = _addDnsCredentialField(s, "dns_dynv6", "DYNV6_TOKEN", "DynV6 Token", ""); + + o = _addDnsCredentialField(s, "dns_dnsimple", "DNSimple_OAUTH_TOKEN", "DNSimple OAuth TOKEN", ""); + + o = _addDnsCredentialField(s, "dns_dgon", "DO_API_KEY", "Digital Ocean API KEY", ""); + + o = _addDnsCredentialField(s, "dns_googledomains", "GOOGLEDOMAINS_ACCESS_TOKEN", "Google Domains Access Token", ""); + o = _addDnsCredentialField(s, "dns_googledomains", "GOOGLEDOMAINS_ZONE", "Google Domains Zone", ""); + + o = _addDnsCredentialField(s, "dns_huaweicloud", "HUAWEICLOUD_Username", "MyHuaweiCloud.com Username", ""); + o = _addDnsCredentialField(s, "dns_huaweicloud", "HUAWEICLOUD_Password", "MyHuaweiCloud.com Password", ""); + o = _addDnsCredentialField(s, "dns_huaweicloud", "HUAWEICLOUD_DomainName", "MyHuaweiCloud.com Domain Name", ""); + + o = _addDnsCredentialField(s, "dns_jd", "JD_ACCESS_KEY_ID", "JDCloud.com Access Key ID", ""); + o = _addDnsCredentialField(s, "dns_jd", "JD_ACCESS_KEY_SECRET", "JDCloud.com Access Key Secret", ""); + o = _addDnsCredentialField(s, "dns_jd", "JD_REGION", "JDCloud.com Region", "cn-north-1"); + + o = _addDnsCredentialField(s, "dns_joker", "JOKER_USERNAME", "Joker.com User", ""); + o = _addDnsCredentialField(s, "dns_joker", "JOKER_PASSWORD", "Joker.com Password", ""); + + o = _addDnsCredentialField(s, "dns_freedns", "FREEDNS_User", "FreeDNS User", ""); + o = _addDnsCredentialField(s, "dns_freedns", "FREEDNS_Password", "FreeDNS Password", ""); + + o = _addDnsCredentialField(s, "dns_linodev4", "LINODE_V4_API_KEY", "Linode API Key", "See acme.sh Wiki: Linode"); + + o = _addDnsCredentialField(s, "dns_mydnsjp", "MYDNSJP_MasterID", "MyDNS.jp MasterID", ""); + o = _addDnsCredentialField(s, "dns_mydnsjp", "MYDNSJP_Password", "MyDNS.jp Password", ""); + + o = _addDnsCredentialField(s, "dns_me", "ME_Key", "DNSMadeEasy Key", ""); + o = _addDnsCredentialField(s, "dns_me", "ME_Secret", "DNSMadeEasy Secret", ""); + + o = _addDnsCredentialField(s, "dns_namecom", "Namecom_Username", "Name.com Username", ""); + o = _addDnsCredentialField(s, "dns_namecom", "Namecom_Token", "Name.com Token", ""); + + o = _addDnsCredentialField(s, "dns_namecheap", "NAMECHEAP_API_KEY", "NameCheap API Key", ""); + o = _addDnsCredentialField(s, "dns_namecheap", "NAMECHEAP_USERNAME", "NameCheap User", ""); + o = _addDnsCredentialField(s, "dns_namecheap", "NAMECHEAP_SOURCEIP", "NameCheap Source IP", ""); + + o = _addDnsCredentialField(s, "dns_nic", "NIC_ClientID", "Nic.ru ClientID", ""); + o = _addDnsCredentialField(s, "dns_nic", "NIC_ClientSecret", "Nic.ru ClientSecret", ""); + o = _addDnsCredentialField(s, "dns_nic", "NIC_Username", "Nic.ru Username", ""); + o = _addDnsCredentialField(s, "dns_nic", "NIC_Password", "Nic.ru Password", ""); + + o = _addDnsCredentialField(s, "dns_netlify", "NETLIFY_ACCESS_TOKEN", "Netlify Access Token", ""); + + o = _addDnsCredentialField(s, "dns_nsupdate", "NSUPDATE_SERVER", "nsupdate server address", ""); + o = _addDnsCredentialField(s, "dns_nsupdate", "NSUPDATE_SERVER_PORT", "nsupdate server port", ""); + o = _addDnsCredentialField(s, "dns_nsupdate", "NSUPDATE_KEY", "nsupdate key file path", ""); + o = _addDnsCredentialField(s, "dns_nsupdate", "NSUPDATE_ZONE", "nsupdate zone", ""); + + o = _addDnsCredentialField(s, "dns_ovh", "OVH_AK", "OVH Application Key", "See acme.sh Wiki: OVH"); + o = _addDnsCredentialField(s, "dns_ovh", "OVH_AS", "OVH Application Secret", ""); + o = _addDnsCredentialField(s, "dns_ovh", "OVH_CK", "OVH Consumer Key", ""); + o = _addDnsCredentialField(s, "dns_ovh", "OVH_END_POINT", "OVH Region/Endpoint", "ovh-eu, ovh-us, ovh-ca, kimsufi-eu, kimsufi-ca, soyoustart-eu, soyoustart-ca"); + + o = _addDnsCredentialField(s, "dns_pdns", "PDNS_Url", "PDNS API URL", ""); + o = _addDnsCredentialField(s, "dns_pdns", "PDNS_ServerId", "PDNS Server ID", ""); + o = _addDnsCredentialField(s, "dns_pdns", "PDNS_Token", "PDNS Token", ""); + o = _addDnsCredentialField(s, "dns_pdns", "PDNS_Ttl", "PDNS Default TTL", "60"); + + o = _addDnsCredentialField(s, "dns_porkbun", "PORKBUN_API_KEY", "Porkbun API Key", ""); + o = _addDnsCredentialField(s, "dns_porkbun", "PORKBUN_SECRET_API_KEY", "Porkbun API Secret", ""); + + o = _addDnsCredentialField(s, "dns_rackspace", "RACKSPACE_Apikey", "RackSpace API Key", ""); + o = _addDnsCredentialField(s, "dns_rackspace", "RACKSPACE_Username", "Porkbun Username", ""); + + o = _addDnsCredentialField(s, "dns_regru", "REGRU_API_Username", "reg.ru Username", ""); + o = _addDnsCredentialField(s, "dns_regru", "REGRU_API_Password", "reg.ru Password", ""); + + o = _addDnsCredentialField(s, "dns_selectel", "SL_Key", "Selectel API Key", ""); + + o = _addDnsCredentialField(s, "dns_simply", "SIMPLY_AccountName", "Simply.com account name", ""); + o = _addDnsCredentialField(s, "dns_simply", "SIMPLY_ApiKey", "Simply.com API Key", ""); + + o = _addDnsCredentialField(s, "dns_vultr", "VULTR_API_KEY", "Vultr API Secret", ""); + + o = _addDnsCredentialField(s, "dns_vscale", "VSCALE_API_KEY", "vscale.io API Key", ""); + + o = s.taboption('challenge', form.DynamicList, "credentials", _("DNS API credentials"), _("The credentials for the DNS API mode selected above. " + "See https://github.com/acmesh-official/acme.sh/wiki/dnsapi for the format of credentials required by each API. " + @@ -278,3 +377,44 @@ return view.extend({ } }) + +function _addDnsCredentialField(s, provider, env, title, desc) { + let o = s.taboption('challenge', form.Value, "_" + env, _(title), + _(desc)); + o.depends("dns", provider); + o.modalonly = true; + o.cfgvalue = function (section_id, stored_val) { + var creds = this.map.data.get(this.map.config, section_id, 'credentials'); + return _extractParamValue(creds, env); + }; + o.write = function (section_id, value) { + this.map.data.set('acme', section_id, 'credentials', [`${env}="${value}"`]) + }; + return o; +} + +/** + * @param {string[]} paramsKeyVals + * @param {string} paramName + * @returns {string} + * @private + */ +function _extractParamValue(paramsKeyVals, paramName) { + if (!paramsKeyVals) { + return ""; + } + for (let i = 0; i < paramsKeyVals.length; i++) { + var paramKeyVal = paramsKeyVals[i]; + var parts = paramKeyVal.split("="); + if (parts.lenght < 2) { + continue; + } + var name = parts[0]; + var val = parts[1]; + if (name == paramName) { + // unquote + return val.substring(0, val.length-1).substring(1); + } + } + return ""; +}